home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Reference / the cmsp digests ('94-'97) / csmp digest Vol 3 No 049 < prev    next >
Internet Message Format  |  1997-05-06  |  113KB

  1. From: pottier@clipper.ens.fr (Francois Pottier)
  2. Subject: csmp-digest-v3-049
  3. Date: Mon, 8 Aug 1994 16:13:56 +0200 (MET DST)
  4.  
  5. C.S.M.P. Digest             Mon, 08 Aug 94       Volume 3 : Issue 49
  6.  
  7. Today's Topics:
  8.  
  9.         CODE resources 101
  10.         Can I do this with the Thread Manager?
  11.         Dice Rolling - answers
  12.         Easy file access functions [source]
  13.         How to detect whether Debugger is installed?
  14.         Q: Converting PB to FSSpec
  15.         Q: Reentrancy and PowerMac Runtime Model
  16.         Std filter proc trashes register D3!
  17.         Which NIM for serial port info?
  18.  
  19.  
  20.  
  21. The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
  22. (pottier@clipper.ens.fr).
  23.  
  24. The digest is a collection of article threads from the internet newsgroup
  25. comp.sys.mac.programmer.  It is designed for people who read c.s.m.p. semi-
  26. regularly and want an archive of the discussions.  If you don't know what a
  27. newsgroup is, you probably don't have access to it.  Ask your systems
  28. administrator(s) for details.  If you don't have access to news, you may
  29. still be able to post messages to the group by using a mail server like
  30. anon.penet.fi (mail help@anon.penet.fi for more information).
  31.  
  32. Each issue of the digest contains one or more sets of articles (called
  33. threads), with each set corresponding to a 'discussion' of a particular
  34. subject.  The articles are not edited; all articles included in this digest
  35. are in their original posted form (as received by our news server at
  36. nef.ens.fr).  Article threads are not added to the digest until the last
  37. article added to the thread is at least two weeks old (this is to ensure that
  38. the thread is dead before adding it to the digest).  Article threads that
  39. consist of only one message are generally not included in the digest.
  40.  
  41. The digest is officially distributed by two means, by email and ftp.
  42.  
  43. If you want to receive the digest by mail, send email to listserv@ens.fr
  44. with no subject and one of the following commands as body:
  45.     help                        Sends you a summary of commands
  46.     subscribe csmp-digest Your Name    Adds you to the mailing list
  47.     signoff csmp-digest            Removes you from the list
  48. Once you have subscribed, you will automatically receive each new
  49. issue as it is created.
  50.  
  51. The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
  52. Questions related to the ftp site should be directed to
  53. scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
  54. digest are available there.
  55.  
  56. Also, the digests are available to WAIS users.  To search back issues
  57. with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use
  58. http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html.
  59.  
  60.  
  61. -------------------------------------------------------
  62.  
  63. >From ikb_macd@ECE.Concordia.CA (Keith MacDonald)
  64. Subject: CODE resources 101
  65. Date: Fri, 15 Jul 1994 05:30:50 GMT
  66. Organization: ECE - Concordia University
  67.  
  68.  
  69. I'd like to be able to distribute files (aka plug-ins) to add features
  70. to a program I'm working on.  These files would (I assume) contain code 
  71. resources.  I've not been able to find any examples or clear description
  72. of what I need to do to achieve this.  I'm using Pascal, but I imagine
  73. C works in a similar manner.
  74.  
  75. Also related to code resources -
  76.     would it be possible to have a C PPC native code resource used by
  77.     a non-native (written in Think Pascal) application?
  78.  
  79. Thanks,
  80. Keith
  81. ..............................................................................
  82. Keith MacDonald                                   A bridge is not a high place 
  83. ikb_macd@ece.concordia.ca                               The fifty-second floor
  84. Computer Engineering                                         Icarus would know
  85. Concordia University                              A mountain isn't far to fall
  86. Montreal, QC, CANADA                          When you've fallen from the moon
  87.                                                                    - Marillion 
  88.  
  89. +++++++++++++++++++++++++++
  90.  
  91. >From mathews@ns9000.furman.edu (Owen Mathews)
  92. Date: 15 Jul 1994 17:03:44 GMT
  93. Organization: furman university computing center
  94.  
  95. Keith MacDonald (ikb_macd@ECE.Concordia.CA) wrote:
  96.  
  97. : I'd like to be able to distribute files (aka plug-ins) to add features
  98. : to a program I'm working on.  These files would (I assume) contain code 
  99. : resources.  I've not been able to find any examples or clear description
  100. : of what I need to do to achieve this.  I'm using Pascal, but I imagine
  101. : C works in a similar manner.
  102.  
  103. : Also related to code resources -
  104. :     would it be possible to have a C PPC native code resource used by
  105. :     a non-native (written in Think Pascal) application?
  106.  
  107. Using code resources to add functionality to an existing program doesn't
  108. require too much modification.  You can "call" a code resource just like
  109. calling a function (see code example below).  The main concept to under-
  110. stand is that code resources can be compiled from souce files just as
  111. an application can be.  The compiler should let you do this when you are
  112. setting all of the options for compiling and linking (in SC++, the menu
  113. option is "Set Project Type").  When the resource is called, the entry
  114. point is simply the main procedure of the file.
  115.  
  116. For more info, see IM.
  117.  
  118. ********************this code example was taken from
  119. ********************Think Reference, copyright Symantec corp.
  120.  
  121. // Calling a Code Resource
  122. // The following code illustrates how to call a
  123. // code resource.  The code resource that we
  124. // are calling is given at the end
  125.  
  126. // Assuming inclusion of <MacHeaders>
  127.  
  128. typedef void (*MyProcPtr) (int);      // Define a procedure pointer
  129.                                             // for the code resource
  130. void DoError (OSErr err);
  131. main ()
  132. {
  133.     Handle myCRHandle;
  134.     ProcPtr myCRPtr;
  135.     int    integerParam;
  136.  
  137.     myCRHandle = GetNamedResource ('ALCT', "\pmyBeep");
  138.     if (myCRHandle == nil)
  139.             DoError (ResError());
  140.     else
  141.     {
  142.             HLock (myCRHandle);
  143.             (* (MyProcPtr) (*myCRHandle)) (integerParam);
  144.             HUnlock (myCRHandle);
  145.     }
  146. }
  147.  
  148. /*********************************************
  149. Here is the code resource that we're calling
  150.  
  151. void main (int i)
  152. {
  153.     int j;
  154.  
  155.     for (j = 0; j < i; j++)
  156.             SysBeep (5);
  157. }
  158. **********************************************/
  159.  
  160.  
  161. : Also related to code resources -
  162. :     would it be possible to have a C PPC native code resource used by
  163. :     a non-native (written in Think Pascal) application?
  164.  
  165. PPC macs do not use the same kind of CODE resources that 68k macs do.
  166. Instead of keeping their program code in the resource fork, divided into 
  167. 32K segments, PowerMacs keep code in the *data* fork of a file.  It may
  168. be possible to call a PPC code chunk from a Pascal application (using the
  169. mixed-mode manager), but it will be a little different than calling a
  170. 68k code resource.
  171.  
  172. --       
  173.        Owen Mathews    mathews@furman.edu
  174.        <><><><><><><><><><><><><><><><><><><><>
  175.        Furman University, Computer Science Dept
  176.  
  177.  
  178. +++++++++++++++++++++++++++
  179.  
  180. >From tyen@netcom.com (Anthony Yen)
  181. Date: Sat, 16 Jul 1994 09:13:13 GMT
  182. Organization: NETCOM On-line Communication Services (408 261-4700 guest)
  183.  
  184. In article <306fhg$fl8@ns9000.furman.edu>,
  185. Owen Mathews <mathews@ns9000.furman.edu> wrote:
  186. >PPC macs do not use the same kind of CODE resources that 68k macs do.
  187. >Instead of keeping their program code in the resource fork, divided into 
  188. >32K segments, PowerMacs keep code in the *data* fork of a file.  It may
  189. >be possible to call a PPC code chunk from a Pascal application (using the
  190. >mixed-mode manager), but it will be a little different than calling a
  191. >68k code resource.
  192.  
  193. Hmm...several questions come to mind as I read this:
  194.  
  195. Has anyone seen how to support calling PPC-native code from within a
  196. PPC-native app?  And from within a fat-app?
  197.  
  198. If I append some application-specific data to the data fork of a
  199. fat-app, it won't confuse the loader or whatever else Apple might have
  200. in store for the data fork in the future, right?  <hope, hope, cross
  201. fingers>
  202.  
  203. Is there a convention for writing fat-code?  That is, can I just build
  204. a CODE resource for 68K, then do what I normally do to build a fat-app
  205. but wave the magic wand over the CODE resource instead, and append the
  206. PPC code onto that resource file and wind up with a fat-loadable code
  207. module?  If I can, is there a single calling convention for both
  208. loadable code modules (this refers back to my first question)?
  209.  
  210. Finally, the THINK Reference code sample appears to add two
  211. dereferences over the standard function call overhead when calling a
  212. code resource.  Is this correct?  If it is correct, in the grand
  213. scheme of things this would not matter, but I may get down to shaving
  214. cycles in the future and if so I may need to have all code resources
  215. locked down in memory and as fully dereferenced as possible.  Offhand,
  216. I see only one dereference I could avoid, by making sure the code
  217. resource is marked locked and getting a pointer out of the handle.
  218. But I'm getting a nagging feeling I'm missing something here...
  219. -- 
  220.  
  221. Anthony Yen <tyen@netcom.com>                           Austin, Texas, USA
  222.  
  223. +++++++++++++++++++++++++++
  224.  
  225. >From jwbaxter@olympus.net (John W. Baxter)
  226. Date: Sat, 16 Jul 1994 10:03:43 -0700
  227. Organization: Internet for the Olympic Peninsula
  228.  
  229. In article <tyenCt10A2.CsB@netcom.com>, tyen@netcom.com (Anthony Yen) wrote:
  230.  
  231. > In article <306fhg$fl8@ns9000.furman.edu>,
  232. > Owen Mathews <mathews@ns9000.furman.edu> wrote:
  233. > >PPC macs do not use the same kind of CODE resources that 68k macs do.
  234. > >Instead of keeping their program code in the resource fork, divided into 
  235. > >32K segments, PowerMacs keep code in the *data* fork of a file.  It may
  236. > >be possible to call a PPC code chunk from a Pascal application (using the
  237. > >mixed-mode manager), but it will be a little different than calling a
  238. > >68k code resource.
  239. > Hmm...several questions come to mind as I read this:
  240. > Has anyone seen how to support calling PPC-native code from within a
  241. > PPC-native app?  And from within a fat-app?
  242.  
  243. Widely available for some time now.
  244. Inside Mac: PowerPC System Software
  245. various "develop" articles
  246. various "MacTech" articles
  247.  
  248. > If I append some application-specific data to the data fork of a
  249. > fat-app, it won't confuse the loader or whatever else Apple might have
  250. > in store for the data fork in the future, right?  <hope, hope, cross
  251. > fingers>
  252.  
  253. The resource which tells the system where to look for the code fragment(s)
  254. provides for this.  But it's probably cleaner not to put variable-length
  255. data in there, or even mutable but fixed length data.
  256.  
  257. > Is there a convention for writing fat-code?  That is, can I just build
  258. > a CODE resource for 68K, then do what I normally do to build a fat-app
  259. > but wave the magic wand over the CODE resource instead, and append the
  260. > PPC code onto that resource file and wind up with a fat-loadable code
  261. > module?  If I can, is there a single calling convention for both
  262. > loadable code modules (this refers back to my first question)?
  263.  
  264. Above references.
  265.  
  266. -- 
  267. John Baxter    Port Ludlow, WA, USA  [West shore, Puget Sound]
  268.    No hablo Intel.
  269.    jwbaxter@pt.olympus.net
  270.  
  271. +++++++++++++++++++++++++++
  272.  
  273. >From winter@ai.rl.af.mil (Jim Wintermyre)
  274. Date: Tue, 19 Jul 1994 19:23:13 GMT
  275. Organization: Rome Laboratory
  276.  
  277. In article <CsyvBJ.Ku3@newsflash.concordia.ca>
  278. ikb_macd@ECE.Concordia.CA (Keith MacDonald) writes:
  279.  
  280. > to a program I'm working on.  These files would (I assume) contain code 
  281. > resources.  I've not been able to find any examples or clear description
  282. > of what I need to do to achieve this.  I'm using Pascal, but I imagine
  283.  
  284. Check out MacTech vol. 9 no. 9 (Sept 93), "External Code Modules in
  285. Pascal."  Also check out the tech note "Stand-Alone Code ad nauseum."
  286.  
  287. > Also related to code resources -
  288. >         would it be possible to have a C PPC native code resource used by
  289. >         a non-native (written in Think Pascal) application?
  290.  
  291. I believe so, but I'm not sure of the details.  Check out the Mixed
  292. Mode and Code Fragment Manager chapters in New Inside Mac: Power PC
  293. System Software.
  294.  
  295. Jim Wintermyre   (Opinions expressed are my own, of course)
  296.  
  297. winter@ai.rl.af.mil
  298. wintermyrej@lonex.rl.af.mil
  299.  
  300. ---------------------------
  301.  
  302. >From amundson@phenom.physics.wisc.edu (James F. Amundson)
  303. Subject: Can I do this with the Thread Manager?
  304. Date: Sat, 16 Jul 1994 21:05:16 -0600
  305. Organization: Division of Information Technology
  306.  
  307. Can someone tell me if what I have in mind is possible? I want to use the
  308. Thread Manager to give me basic preemptive multitasking without much
  309. thought.
  310.  
  311. My situation is this: I'm not writing a Mac application. I'm using Think C
  312. 7.0 to run scientific calculations. My programs are entirely ANSI C with
  313. no toolbox calls other than those from the Think C ANSI libraries. I'd
  314. like to be able to run the programs I write without taking over my mac
  315. while they run. In the past, I've hacked them to call WaitNextEvent
  316. occasionally. The problem is that it takes a fair amount of effort on my
  317. part to decide where and how often I need to call WNE. Since the nature of
  318. my work involves constantly changing the programs I'm writing, adjusting
  319. my calls to WNE every time is impractical. 
  320.  
  321. Can I use the Thread Manager without much effort? Are there any examples
  322. of this sort of thing?
  323.  
  324. Any advice will be appreciated.
  325.  
  326. Thanks,
  327.  
  328. Jim Amundson
  329.  
  330. +++++++++++++++++++++++++++
  331.  
  332. >From first.ascent@mindlink.bc.ca (Alex Curylo)
  333. Date: 17 Jul 1994 03:17:02 GMT
  334. Organization: MIND LINK! Communications Corp.
  335.  
  336. In article <amundson-1607942105160001@f180-186.net.wisc.edu>
  337. amundson@phenom.physics.wisc.edu (James F. Amundson) writes:
  338.  
  339. > Can I use the Thread Manager without much effort? Are there any examples
  340. > of this sort of thing?
  341.  
  342. Grab develop 17, and a copy of CodeWarrior 3.5. The latest iteration of
  343. PowerPlant includes a nice selection of thread classes. They're being
  344. used in a project I'm working on right now, and the fellow using them
  345. seems to have fairly positive regard for them. And for the rest of
  346. PowerPlant, as soon as they finish it ;)
  347.  
  348. +++++++++++++++++++++++++++
  349.  
  350. >From rmah@panix.com (Robert Mah)
  351. Date: Sun, 17 Jul 1994 00:53:05 -0500
  352. Organization: One Step Beyond
  353.  
  354. amundson@phenom.physics.wisc.edu (James F. Amundson) wrote:
  355.  
  356. ) I'm using Think C 7.0 to run scientific calculations. My programs are
  357. ) entirely ANSI C with no toolbox calls other than those from the Think
  358. ) C ANSI libraries. I'd like to be able to run the programs I write
  359. ) without taking over my mac while they run. In the past, I've hacked
  360. ) them to call WaitNextEvent occasionally. The problem is that it takes
  361. ) ...
  362. ) Can I use the Thread Manager without much effort? Are there any examples
  363. ) of this sort of thing?
  364.  
  365. Thread Manager can do pre-emptive threads, _but_ only on 68K Macs.  In
  366. addition, pre-emptive threads must obey the same rules as interupt level
  367. code.  I.e. no drawing, no moving memory, etc.
  368.  
  369. There's examples in Develop 17 that goes over using the Thread Mgr, but
  370. since using co-operative threads won't gain you much (you'll still have
  371. to call Yield() occaisionally) you should look at your code and see if
  372. you can use pre-emptive threads.
  373.  
  374. Cheers,
  375. Rob
  376. _____________________________________________________________________
  377. Robert S. Mah    :  Macintosh software development  :    212.947.6507
  378. One Step Beyond  :      and network consulting      :  rmah@panix.com
  379.  
  380. +++++++++++++++++++++++++++
  381.  
  382. >From gwatts@fnal.fnal.gov (Gordon Watts)
  383. Date: Mon, 18 Jul 1994 00:09:54 -0600
  384. Organization: Fermi Lab
  385.  
  386. In article <rmah-1707940053050001@rmah.dialup.access.net>, rmah@panix.com
  387. (Robert Mah) wrote:
  388.  
  389. > amundson@phenom.physics.wisc.edu (James F. Amundson) wrote:
  390. > ) I'm using Think C 7.0 to run scientific calculations. My programs are
  391. > ) entirely ANSI C with no toolbox calls other than those from the Think
  392. > ) C ANSI libraries. I'd like to be able to run the programs I write
  393. > ) without taking over my mac while they run. In the past, I've hacked
  394. > ) them to call WaitNextEvent occasionally. The problem is that it takes
  395. > ) ...
  396. > ) Can I use the Thread Manager without much effort? Are there any examples
  397. > ) of this sort of thing?
  398. > Thread Manager can do pre-emptive threads, _but_ only on 68K Macs.  In
  399. > addition, pre-emptive threads must obey the same rules as interupt level
  400. > code.  I.e. no drawing, no moving memory, etc.
  401. > There's examples in Develop 17 that goes over using the Thread Mgr, but
  402. > since using co-operative threads won't gain you much (you'll still have
  403. > to call Yield() occaisionally) you should look at your code and see if
  404. > you can use pre-emptive threads.
  405. > Cheers,
  406. > Rob
  407.  
  408. It depends upon what ANSI C library calls you make.  If you make calls to
  409. printf, etc. then the short answer is ... well, no.  Calls to things like
  410. sqrt, etc. are ok.  Basically, any call that will cause the screen to be
  411. drawn to or memory to be moved (malloc, etc.) will break with the
  412. pre-emptive threads.
  413.  
  414. There are two things you can do, if you still want to use the threads. 
  415. First, you can isolate your calls to printf and the like so they are never
  416. called in a preemptive thread (a thread is preemptive or cooperative when
  417. it is created, and cannot change during its lifetime).
  418.  
  419. Second, and perhaps simpler, is you can implement your calculation as a
  420. cooperative thread.  Sprinkle calls to "Yield()" all over the place, but
  421. don't worry too much about the placement.  Just make sure there are enough
  422. of them.  Now, in your main event loop you can put something like the
  423. following (this code has not been compiled/debugged!):
  424.  
  425. while (!gDone) {  // gDone will be set by your calc when it is finished...
  426.  
  427.   current_time = TickCount () + 30;  // Current time plus 1/2 a second
  428.  
  429.   while (current_time > TickCount ())
  430.     Yield ();  // Go off and do some real calculations for a 1/2 second
  431.  
  432.   WaitNextEvent (...);
  433. }
  434.  
  435. Excuse the formatting... You will incure dead time in the Yield call, I'm
  436. not sure how much speed you are trying to get out.  The fact that you are
  437. calling WaitNextEvent means that you are willing to give up some time... 
  438. This will require little modification to your current application, I
  439. suspect.
  440.  
  441. One bad thing about using threads if you have to figure out what your
  442. stack usage is before you run your calculation -- threads don't have a
  443. stack that grows as need be.  This might be bad if you are doing lattice
  444. calculations and allocate large arrays on the stack (do it globally at
  445. compile time or by malloc while running).
  446.  
  447. You can use all calls in cooperative threads, printf, malloc, etc. etc.
  448. and they will work on the powerpc.
  449.  
  450. Cheers,
  451.    Gordon (high energy physics).
  452.  
  453. -- 
  454. Gordon Watts -- gwatts@fnal.fnal.gov
  455.  
  456. +++++++++++++++++++++++++++
  457.  
  458. >From Dave Falkenburg <falken@apple.com>
  459. Date: Wed, 20 Jul 1994 16:43:41 GMT
  460. Organization: Apple Computer, Inc.
  461.  
  462. In article <gwatts-1807940009540001@slip113.fnal.gov> Gordon Watts,
  463. gwatts@fnal.fnal.gov writes:
  464. >while (!gDone) {  // gDone will be set by your calc when it is
  465. finished...
  466. >
  467. >  current_time = TickCount () + 30;  // Current time plus 1/2 a second
  468. >
  469. >  while (current_time > TickCount ())
  470. >    Yield ();  // Go off and do some real calculations for a 1/2 second
  471. >
  472. >  WaitNextEvent (...);
  473. >}
  474.  
  475.  
  476. GACK!
  477.  
  478. Please use a dynamic value for adjusting sleep timings like this: i.e.
  479. replace the "+30" with "+gRunQuantum", a value that is computed
  480. dynamically based on the compute power of the CPU.  The code above means
  481. that even if we make the MacOS 100x faster, you might limit the ability
  482. for the user to switch applications down to once every two seconds.
  483.  
  484. HALF A SECOND IS ALOT OF CPU TIME TO BE EATING without yielding control
  485. to other applications.
  486.  
  487. -Dave Falkenburg
  488. -Apple Computer, Inc.
  489.  
  490. ---------------------------
  491.  
  492. >From cconstan@epdiv1.env.gov.bc.ca (Carl B. Constantine)
  493. Subject: Dice Rolling - answers
  494. Date: Thu, 21 Jul 1994 08:12:12 -0700
  495. Organization: Ministry of Environment, Lands & Parks
  496.  
  497. Finally, after much fiddling and examining of code, I finally got my dice
  498. animation working in my game.  There is a trick to it.
  499.  
  500. Because many people helped me, I thought I would post what I found so that
  501. others can be helped too.
  502.  
  503. First, a little background.  I use 3 global GWorlds to hold (a) all six
  504. dice from a PICT resource, (b) the mask and (c) a working area.  This set
  505. up is similar to how john calhoun did his games like Glypa II.  As
  506. mentioned above, these are all global, so I can access them from
  507. anywhere.  I also use a custom window record structure that includes a
  508. GWorld which has the contents of the window in it.  This is used for
  509. really fast updates (See Mac Prog. Secrets, ch 6 for more details)
  510.  
  511. Now that all the GWorlds are set up and the items are in them, I use
  512. CopyMask (speed is not important in this game) to copy the dice from the
  513. diceWorld and the mask from the maskWorld to the workWorld. (with me so
  514. far?)  This is a simple call.  I use it twice as I have 2 dice I want to
  515. display and "roll".  I can then use CopyBits to copy the workWorld to my
  516. window's offscreen GWorld for updating purposes.  No problems here.
  517.  
  518. The trick comes when you want to copy the dice from the GWorld to the
  519. window.  When you use GWorlds, you always use GetGWorld and SetGWorld when
  520. copying from 1 GWorld to another.  However, if you use this when you want
  521. to copy to the window, CopyBits makes your Mac CRASH big time!! (I ran
  522. this in the debugger in THINK C 7.0.3 and I still couldn't get out. 
  523. cmd-opt-esc didn't do much, I had to restart.  I have an LCIII with 12MB
  524. RAM).  So what you have to do is use GetPort and SetPort when copying to
  525. the window.  This works without a hitch.  
  526.  
  527. I then use CopyMask as I did before to copy the dice to the workWorld and
  528. CopyBits to copy from the workWorld to the window.  This is still pretty
  529. fast despite the intermediate steps.  I've seen some code by Tony Myles
  530. that I got off of ftp.apple.com called CopyBits vs. CopyMask.  He uses
  531. CopyBits with a maskRgn to copy to the window.  This is much faster.  But
  532. like I said, I don't need speed.  Also, you can just plain elimate the
  533. intermate step and CopyMask directly to the window instead of the
  534. workWorld and then the window.
  535.  
  536. Thanks to many people on the Net for donating code (Ken Long) and help
  537. (Aaron Giles, Ingemar R., et al.) so that I can actually get this to work.
  538.  
  539. -- 
  540. ========================================================================
  541. Carl B. Constantine                  B.C. Environment, Lands & Parks
  542. End-User Support Analyst             CCONSTAN@epdiv1.env.gov.bc.ca
  543.  PGP Key available if you finger: CCONSTAN@EUSACBC.env.gov.bc.ca
  544.  
  545. +++++++++++++++++++++++++++
  546.  
  547. >From s828963@kub.nl (Peter Berck)
  548. Date: 22 Jul 1994 12:21:53 GMT
  549. Organization: KUB, The Netherlands
  550.  
  551. In article <cconstan-2107940812120001@eusacbc.env.gov.bc.ca>, cconstan@epdiv1.env.gov.bc.ca (Carl B. Constantine) writes:
  552. |> Finally, after much fiddling and examining of code, I finally got my dice
  553. |> animation working in my game.  There is a trick to it.
  554. |> 
  555. |> Because many people helped me, I thought I would post what I found so that
  556. |> others can be helped too.
  557. |> 
  558. [snip]
  559. |> 
  560. |> The trick comes when you want to copy the dice from the GWorld to the
  561. |> window.  When you use GWorlds, you always use GetGWorld and SetGWorld when
  562. |> copying from 1 GWorld to another.  However, if you use this when you want
  563. |> to copy to the window, CopyBits makes your Mac CRASH big time!! (I ran
  564. |> this in the debugger in THINK C 7.0.3 and I still couldn't get out. 
  565. |> cmd-opt-esc didn't do much, I had to restart.  I have an LCIII with 12MB
  566. |> RAM).  So what you have to do is use GetPort and SetPort when copying to
  567. |> the window.  This works without a hitch.  
  568.  
  569. Uhm? Are you sure? I am writing a program which also has an offscreen
  570. GWorld which is copied to the screen (using CopyBits) when necessary.
  571. I use SetGWorld and GetGWorld all the time. In fact, NIM:Imaging with
  572. QuickDraw mentions somewhere (don't have it on me, so I can't give you
  573. the page number) that you should use SetGWorld/GetGWorld instead of
  574. GetPort and SetPort.
  575.  
  576. Now I'm slightly confused. I have just started to use GWorld stuff,
  577. and I was pretty sure that Get/SetGWorld was all I needed, so if any
  578. macguru can enlighten me I'd be very grateful...
  579.  
  580. -Peter
  581.  
  582. - ----------------------------------------------------------------
  583. P.J.Berck@kub.nl                             pgp-pubkey on request
  584. (format t "~&~{~<~%~1:;~a~>~^,~}.~%"
  585.    '(DoD#-337 The-Ex Sonic-Youth NIN Dante-Alighieri Guinness))
  586.  
  587. +++++++++++++++++++++++++++
  588.  
  589. >From cconstan@epdiv1.env.gov.bc.ca (Carl B. Constantine)
  590. Date: Fri, 22 Jul 1994 11:30:50 -0700
  591. Organization: Ministry of Environment, Lands & Parks
  592.  
  593. In article <30odl1$7ro@kubds1.kub.nl>, P.J.Berck@kub.nl wrote:
  594.  
  595. > In article <cconstan-2107940812120001@eusacbc.env.gov.bc.ca>,
  596. cconstan@epdiv1.env.gov.bc.ca (Carl B. Constantine) writes:
  597. > |> Finally, after much fiddling and examining of code, I finally got my dice
  598. > |> animation working in my game.  There is a trick to it.
  599. > |> 
  600. > |> Because many people helped me, I thought I would post what I found so that
  601. > |> others can be helped too.
  602. > |> 
  603. > [snip]
  604. > |> 
  605. > |> The trick comes when you want to copy the dice from the GWorld to the
  606. > |> window.  When you use GWorlds, you always use GetGWorld and SetGWorld when
  607. > |> copying from 1 GWorld to another.  However, if you use this when you want
  608. > |> to copy to the window, CopyBits makes your Mac CRASH big time!! (I ran
  609. > |> this in the debugger in THINK C 7.0.3 and I still couldn't get out. 
  610. > |> cmd-opt-esc didn't do much, I had to restart.  I have an LCIII with 12MB
  611. > |> RAM).  So what you have to do is use GetPort and SetPort when copying to
  612. > |> the window.  This works without a hitch.  
  613. > Uhm? Are you sure? I am writing a program which also has an offscreen
  614. > GWorld which is copied to the screen (using CopyBits) when necessary.
  615. > I use SetGWorld and GetGWorld all the time. In fact, NIM:Imaging with
  616. > QuickDraw mentions somewhere (don't have it on me, so I can't give you
  617. > the page number) that you should use SetGWorld/GetGWorld instead of
  618. > GetPort and SetPort.
  619. > Now I'm slightly confused. I have just started to use GWorld stuff,
  620. > and I was pretty sure that Get/SetGWorld was all I needed, so if any
  621. > macguru can enlighten me I'd be very grateful...
  622.  
  623. It crashed my mac considerably.  However, I'm piggybacking a GWorldPtr
  624. onto a custom windowRecord structure.  this may be why it's crashing.  I'm
  625. not sure, I haven't tested it otherwise (I don't have NIM: Imaging).  I'd
  626. have to test.
  627.  
  628. I have it off hand from a good source (Aaron Giles, writer of JPEGView)
  629. that you SHOULD always used GetGWorld & SetGWorld.  I'm not sure why it
  630. was crashing in my system, but it was so I left it with GetPort & SetPort.
  631.  
  632. Hope this helps.
  633.  
  634. -- 
  635. ========================================================================
  636. Carl B. Constantine                  B.C. Environment, Lands & Parks
  637. End-User Support Analyst             CCONSTAN@epdiv1.env.gov.bc.ca
  638.  PGP Key available if you finger: CCONSTAN@EUSACBC.env.gov.bc.ca
  639.  
  640. +++++++++++++++++++++++++++
  641.  
  642. >From kenlong@netcom.com (Ken Long)
  643. Date: Sat, 23 Jul 1994 14:24:16 GMT
  644. Organization: NETCOM On-line Communication Services (408 261-4700 guest)
  645.  
  646. Here are some fragments/snippets from Mark Hanrek, on the subjuct, ala 
  647. NuCube (some names changed for another program):
  648.  
  649. - -----------
  650. WindowPtr starsWindow;        // Windows and GWorlds are the same thing, so
  651. GWorldPtr gOffscreenGWorld; // use only Get/SetGWorld calls in 
  652.                 // this app.screen" area in the window
  653. Rect gOffscreenRect;        // The offscreen rect's upper-left is 0,0
  654. Rect gProjectionRect;        // The projection Rect
  655.  
  656. //*******************************************************************//
  657. //  Create window, offscreen GWorld, and one control for starters     //
  658. //*******************************************************************//
  659.  
  660. void SetupWindow (void) 
  661. {
  662.     Rect    tempRect;
  663.     
  664.     //------ Set up our main window, man
  665.  
  666.     starsWindow = GetNewWindow (rWIND, nil, (WindowPtr) -1L);
  667.     
  668.     SetPort (starsWindow);
  669.     ShowWindow (starsWindow);
  670.  
  671.     SetRect (&gProjectionRect, kHorizOffset, kVertOffset,  
  672.           kHorizOffset+kCubeSide, kVertOffset+kCubeSide);
  673.  
  674.     //¥ Set up an offscreen GWorld for preparing the next cube's image.
  675.     SetRect (&gOffscreenRect, 0, 0, kCubeSide, kCubeSide);
  676.     
  677.     gOffscreenGWorld = CreateOffscreenGWorld (&gOffscreenRect);
  678.     
  679. }
  680.  
  681. void RotateCubeOnce (void)
  682. {
  683.     long            ticksNow;
  684.     GWorldPtr        windowGW;
  685.     GDHandle        windowGD;
  686.     PixMapHandle    thePixMap;
  687.  
  688.     GetGWorld (&windowGW, &windowGD);     // Save whatever we had before
  689.  
  690.     SetGWorld (gOffscreenGWorld, nil);
  691.  
  692.     if (LockPixels (thePixMap = GetGWorldPixMap (gOffscreenGWorld)))
  693.     {
  694.         EraseRect (&gOffscreenGWorld->portRect);
  695.  
  696.     //======================================================
  697.     (action)
  698.     //======================================================
  699.     //
  700.     //  Always set the current port to a window's port before 
  701.     // drawing from
  702.     //  a GWorld, so that the Window Manager can "clip" the 
  703.     // image properly
  704.     //  should there be other windows in front. Comment out 
  705.     // the next statement
  706.     //  and notice what happens when you drag another window in front of 
  707.     //  the NuCube window.  :)
  708.     //
  709.         
  710.     SetGWorld (windowGW, windowGD);  // Focus on a real window
  711.  
  712.     CopyBits ((BitMapPtr)*thePixMap, 
  713.           (BitMapPtr)&starsWindow->portBits, 
  714.            &gOffscreenRect, 
  715.            &gProjectionRect, srcCopy, nil);
  716.  
  717.     UnlockPixels (thePixMap);
  718.     }
  719.     SetGWorld (windowGW, windowGD); // Okay if this is redundant
  720. }
  721.  
  722. //*******************************************************************//
  723. //  Use the following function for the rest of your programming      
  724. //  days. 
  725. //  Do not alter it in any way. It is a complete functional unit
  726. //  doing all REQUIRED things.
  727. //*******************************************************************//
  728.  
  729. GWorldPtr CreateOffscreenGWorld (Rect *theRect)
  730. {
  731.     CGrafPtr    currentPort;
  732.     GDHandle    currentGDevice;
  733.     GWorldPtr   offScreen;
  734.     QDErr       result;
  735.  
  736.     GetGWorld (¤tPort, ¤tGDevice);
  737.     
  738.     //-- If there is not enough application memory, try MultiFinder 
  739.     //-- temporary memory.
  740.     
  741.     if ((result = NewGWorld (&offScreen, 0, theRect, nil, nil, 0L)) 
  742.         != noErr)
  743.         if ((result = NewGWorld (&offScreen, 0, theRect, nil, 
  744.             nil, useTempMem)) != noErr)
  745.             return (nil);
  746.             
  747.     SetGWorld (offScreen, nil);
  748.     
  749.     //-- Initialize the clipping "hole" to be the same as the 
  750.     //-- drawing area.
  751.  
  752.     ClipRect (&offScreen->portRect);    
  753.  
  754.     //-- The GWorld has random stuff in it, so we'll erase it to 
  755.     //-- white.
  756.     
  757.     if (LockPixels (GetGWorldPixMap (offScreen)))
  758.     {
  759.         ForeColor (blackColor);
  760.         BackColor (whiteColor);
  761.         EraseRect (&offScreen->portRect);
  762.         UnlockPixels (GetGWorldPixMap (offScreen));
  763.     }
  764.  
  765.     SetGWorld (currentPort, currentGDevice);
  766.     return offScreen;
  767. }
  768.  
  769. //*******************************************************************//
  770. // Shut down with charm, grace and decorum.
  771. //*******************************************************************//
  772.  
  773. void MoveAlongHome (void) 
  774. {
  775.     DisposeWindow (starsWindow);        // Not "CloseWindow"
  776.     DisposeGWorld (gOffscreenGWorld); 
  777. }
  778.  
  779. - --------------
  780. That's all, folks.
  781.  
  782. -Ken-
  783.  
  784. ---------------------------
  785.  
  786. >From rkwee@ee.pdx.edu (Roland Kwee)
  787. Subject: Easy file access functions [source]
  788. Date: 18 Jul 1994 20:35:28 -0700
  789. Organization: (none)
  790.  
  791. Some days ago I promised to upload some source code that makes handling
  792. Mac file functions as easy as the standard ANSI C library functions.
  793. Hopefully I didn't leave out code that is essential to understand and
  794. use my little system.
  795.  
  796. Here is my Macintosh ThinkC source code for accessing files pretty much like
  797. with the ANSI C library functions. Hopefully the code is sufficiently
  798. commented to be understandible. Note that there is a test function that
  799. demonstrates how to use the other functions.
  800.  
  801. Please let me know if this is useful, understandable, and if you see
  802. problems or improvements.
  803.  
  804. --Roland Kwee         email: RolandKwee@ACM.org
  805.  
  806. /*----------------------------------------------------------------------------------
  807.  * globals.h    Roland Kwee    May 25, 1994
  808.  * This file contains the declarations for the application-specific global data. 
  809.  *
  810.  * A good strategy may be to declare a number of global variables in a single
  811.  * structure. With the menu options, the user can change one or more of these
  812.  * global settings. These settings are global to allow easy access by the
  813.  * functions that actually perform tasks. By keeping them in a single
  814.  * structure, they are easy to keep track of.
  815.  *----------------------------------------------------------------------------------
  816.  */
  817.  
  818. #ifndef __GLOBALS_H__
  819. #define __GLOBALS_H__
  820.  
  821. enum Creators{CREATOR='TrRK'};
  822.  
  823. enum FileTypes{UNKNOWN, PostScript, Binary, 
  824.     TextDos, TextUnix, TextMac, 
  825.     Hathaway, Rochester, RochesterHeader, BEN5000, 
  826.     PPSM, Support, Spreadsheet};
  827.  
  828. /* This structure communicates user input to the process. */
  829. struct Option_s{
  830.     int Quit;
  831.     int SeparateDigCh, OutputType, LPFcorrection, DiagnosticWindow, ProgressDialog, Fast;
  832.     int debug, test_partly;   /* default: 0 (no debug output). */
  833.     void *OpenFileList, *PrintFileList;
  834.     float TimeZoneHourOffset;
  835.     char DefaultLocation[5];
  836. };
  837.  
  838. extern struct Option_s Option;
  839.  
  840. #endif /* __GLOBALS_H__ */
  841.  
  842.  
  843.  
  844.  
  845. /* MacFile.h   Roland Kwee   June 1, 1994 
  846.  * Functions to make handling files on the Mac almost as easy as in Unix.
  847.  * This will make it possible to port programs between Unix and the Mac.
  848.  */
  849.  
  850.  
  851. #ifndef _MACUTIL_H__
  852. #define _MACUTIL_H__
  853.  
  854. #include <stdio.h>
  855. #include <stdlib.h>
  856. #include <string.h>
  857. #include <errno.h>
  858.  
  859. //==============
  860. // Project Info:
  861. //==============
  862. // compiler: Symantec C++ for Macintosh, 1994, ThinkC (version 7 ?)
  863. // libraries: MacTraps, SANE, ANSI
  864.  
  865. // Executable:
  866. // file name: Translate
  867. // File Type: APPL, Creator: TrRK
  868.  
  869. // Compiler settings:
  870. // int: 2 bytes
  871. // float: 4 bytes
  872. // double: 8 bytes
  873. // don't use the "native" floating point format
  874. #if __option(native_fp)
  875. #error Don't use the "native" floating point format (Edit/Options/Compiler settings).
  876. #endif
  877. // printf can only handle float and doubles if double is not set to 8 bytes:
  878. #if __option(double_8)
  879. #error Don't set doubles to 8 bytes (Edit/Options/Compiler settings).
  880. #endif
  881. // REASONS FOR FLOATING POINT SETTINGS:
  882. // The input file has IEEE double numbers, but the input routine is able to convert these
  883. // to Mac format using the Mac type `short double' which is equal to IEEE double.
  884. // The library function printf is compiled with the standard settings, so the formats for
  885. // floating point will work incorrectly if the program is compiled with the `8-byte doubles' option.
  886. // Better not to recompile the library, so set all floating point options to Mac standard.
  887.  
  888.  
  889.  
  890. /* ===============definitions for byte order ===================== */
  891. enum {BigEndian /* Motorola, VAX */, LittleEndian /* Intel */};
  892.                             
  893. //extern int     computerbyteorder;
  894. #define computerbyteorder BigEndian
  895.  
  896. /*=========================== TIME ZONE ============================*/
  897. /* This should be a menu option. For now it is constant. 
  898.  * Valid values are -12.0 .. 12.0. Positive is East of Greenwich.
  899.  * Simple fractions like 9.5 (Adelaide, Australia) should work.
  900.  */
  901. #define TZ -7
  902.  
  903. /* This global can be used with sprintf to prepare a string to pass to Log(). */
  904. extern char buf[1000];
  905.  
  906. void Log(char *msg);
  907. void SystemError(char *msg, char *source, int code);
  908. void Warn(char *msg);
  909. char *PtoCstrPtr(void *Pstring);
  910. void LtoCstr(OSType l, char *s);
  911. char *FSStoCstrPtr(FSSpec *file);
  912. char *GetBaseName(FSSpec *file);
  913. char *GetFullPathName(FSSpec *file);
  914. void GetFullPath(int VolumeSpec, long ParentDirID, char *fullPath);
  915. int FSSpecRoutinesAvail(void);
  916. FSSpec *select_input_file(const int numTypes, SFTypeList myTypes);
  917. FSSpec *select_output_file(const char *prompt, const char *defname);
  918. void FinderInfo(FSSpec *fs);
  919. void PathInfo(FSSpec *fs);
  920. char *GetVolumeName(FSSpec *fs);
  921. void VolumeInfo(FSSpec *fs);
  922. void TestPathUtils(void);
  923.  
  924. #if 0    /* See Mac include file <files.h> */                                                                      
  925. struct FSSpec {                                                           
  926.     short vRefNum;                                                        
  927.     long parID;                                                           
  928.     Str63 name;                                                           
  929. };                                                                                                                                                  
  930. typedef struct FSSpec FSSpec;                                             
  931. typedef FSSpec *FSSpecPtr, **FSSpecHandle;                                                                                                          
  932. typedef FSSpecPtr FSSpecArrayPtr;       /* pointer to array of FSSpecs */ 
  933. #endif
  934.  
  935. typedef struct{
  936.     int     in_use;    /* To maintain the file table. */
  937.     FSSpec     fss;    /* Specification of the (closed) file selected with a dialog. */
  938.     short    refnum; /* Reference number, or access path of the open file. */
  939.     int        byteorder;
  940. }MacFILE;
  941.  
  942. /* This structure is currently only used to hold the year of a file.
  943.  * It doesn't really matter whether last access or last modify.
  944.  */
  945. struct MacStat{
  946.    long     st_size;       /* total size of file, in bytes */ 
  947.    int        year;
  948. #if 0 
  949.    time_t    st_atime;      /* file last access time */         
  950.    time_t    st_mtime;      /* file last modify time */         
  951.    time_t    st_ctime;      /* file last status change time */  
  952. #endif    
  953. };
  954.  
  955. #define File         MacFILE
  956. #define FileRead     macfread
  957. #define FWRITE        macfwrite
  958. #define FSEEK       macfseek
  959. #define FSTAT        macfstat
  960. #define STAT_T      struct MacStat
  961.  
  962. MacFILE *macftype(FSSpec *selection, long creator, long type);
  963. MacFILE *macfopen(FSSpec *selection, char *mode);
  964. int macfclose(MacFILE *fp);
  965. int macfread(void *buf, size_t recsize, size_t recnum, MacFILE *fp);
  966. int macfwrite(void *buf, size_t recsize, size_t recnum, MacFILE *fp);
  967. int macfseek(MacFILE *fp, long offset, int whence);
  968. long macftell(MacFILE *fp);
  969. int macfstat(MacFILE *fp, struct MacStat *buf);
  970. void copy_file(MacFILE *fp_in, MacFILE *fp_out);
  971. int TestFileType(MacFILE *fp);
  972. void TestFileUtils(void);
  973. void BetterMoveWindow(WindowPtr wp, float right, float down);
  974.  
  975. void SwapN(void *buf, int n);
  976. int NeedSwap(MacFILE *fp, void *buf, int n);
  977.  
  978. char GetInputByte(File *fp); // Reads and returns one byte.
  979. int  GetInputInt(File *fp); // Reads, converts and returns one integer.
  980. long GetInputLong(File *fp);
  981. unsigned long GetInputULong(File *fp);
  982. float GetInputFloat(File *fp);
  983. double GetInputDouble(File *fp); /* reads IEEE 8-byte double, returns Mac double. */
  984.  
  985. /* GetInputString - Reads a string and returns a null-terminated C-string.
  986.                     Reading stops when a '\0' char,  or `size' characters have
  987.                     been read. A '\0' is added.
  988. If you are certain that the string to read is terminated with a '\0', 
  989. then `size' can be the size of the buffer. Otherwise, the buffer needs to be 
  990. one character bigger, to hold the added '\0'.
  991. */
  992. char *GetInputString(char *buf, int size, File *fp);
  993.  
  994. /* GetInputNString - Reads n characters and returns a string in str. 
  995.                     str needs to have room for an additional '\0'. */
  996. char *GetInputNString(char *str, int n, File *fp);
  997.  
  998. /* SwapN - swaps n bytes of buf in place */
  999. void SwapN(void *buf, int n);
  1000.  
  1001.  
  1002. // Writes a C string to the output file.
  1003. int WriteTxt(File *fp, char *str);
  1004.  
  1005. // Writes bytes to a binary output file.
  1006. int WriteBin(File *fp, void *buf, int size);
  1007.  
  1008. // Specialized functions to write data, argument may be a constant
  1009. void WriteULong(File *fp, unsigned long x);
  1010. void WriteLong(File *fp, long x);
  1011. void WriteShort(File *fp, signed short x);
  1012.  
  1013. #endif /* _MACUTIL_H__ */
  1014.  
  1015.  
  1016. /* MacFile.c   Roland Kwee   June 1, 1994 
  1017.  * Functions to make handling files on the Mac almost as easy as in Unix.
  1018.  * This will make it possible to port programs between Unix and the Mac.
  1019.  */
  1020.  
  1021. #include "MacFile.h"
  1022. #include "globals.h"
  1023. #include <GestaltEqu.h>
  1024. #include <console.h> /* cshow() */
  1025.  
  1026. /* This global can be used with sprintf to prepare a string to pass to Log(). */
  1027. char buf[1000];
  1028.  
  1029. /*----------------------------------------------------------------------------------
  1030.  * Log() - Diagnostic output. Adds a newline at the end.
  1031.  *----------------------------------------------------------------------------------*/
  1032. void Log(char *msg){
  1033.     if(Option.debug)
  1034.         puts(msg);
  1035.     return;
  1036. }
  1037.  
  1038. /*----------------------------------------------------------------------------------
  1039.  * SystemError() - Error output. Should be a alert box.
  1040.  *----------------------------------------------------------------------------------*/
  1041. void SystemError(char *msg, char *source, int code){
  1042.  
  1043.     /* Force visible output. */
  1044.     if(!Option.debug){
  1045.         Option.debug=1;
  1046.         cshow(stdout);
  1047.     }
  1048.     
  1049.     sprintf(buf, "Error: %s%s%s code: %d", msg, source?" in function: ":"",
  1050.         source?source:"", code);
  1051.     Log(buf);
  1052.     
  1053.     return;
  1054. }
  1055.  
  1056. /*----------------------------------------------------------------------------------
  1057.  * Warn() - Warning output.
  1058.  *
  1059.  * Should be a modal dialog box IF the diagnostic window is closed.
  1060.  * Or, there should be an option to suppress the modal dialog box to
  1061.  * allow unattended transfer of large batches of files.
  1062.  *
  1063.  *----------------------------------------------------------------------------------*/
  1064. void Warn(char *msg){
  1065.     Log(msg);
  1066.     return;
  1067. }
  1068.  
  1069. /*----------------------------------------------------------------------------------
  1070.  * PtoCstrPtr() - Converts a Pascal string to a pointer to a C String.
  1071.  *                The string the pointer points to is reused for each new call.
  1072.  *----------------------------------------------------------------------------------*/
  1073. char *PtoCstrPtr(void *Pstring){
  1074.     static char Cstring[257];
  1075.     char *str;
  1076.     int i, max;
  1077.     
  1078.     str=Pstring;
  1079.     max=str[0];
  1080.     memcpy(Cstring, str+1, max);
  1081.     Cstring[max]='\0';
  1082.     return Cstring;
  1083. }
  1084.  
  1085. /*----------------------------------------------------------------------------------
  1086.  * LtoCstr() - Converts an OSType (long) to a C-string (char[5]).
  1087.  *----------------------------------------------------------------------------------*/
  1088. void LtoCstr(OSType l, char *s){
  1089.     //sprintf(buf, "LtoCstr: 0x%08X", l); Log(buf); 
  1090.     memcpy(s, (char*)&l, 4);
  1091.     s[4]='\0';
  1092.     return;
  1093. }
  1094.  
  1095. /*----------------------------------------------------------------------------------
  1096.  * FSStoCstrPtr() - Converts a FSS file specification to a C string.
  1097.  *                The string the pointer points to is reused for each new call.
  1098.  * See: New Inside Mac, "Files", p. 2-45: Constructing Full Pathnames, Listing 2-5.
  1099.  *----------------------------------------------------------------------------------*/
  1100. char *FSStoCstrPtr(FSSpec *file){
  1101.     static char    fullPath[300];
  1102.     CInfoPBRec    myPB;
  1103.     Str255         dirName;
  1104.     OSErr        myErr;
  1105.     
  1106.     strcpy(fullPath, PtoCstrPtr(file->name));/* Start with base file name. */
  1107.     myPB.dirInfo.ioNamePtr=dirName;            /* Output buffer for PBGetCatInfo(). */
  1108.     myPB.dirInfo.ioVRefNum=file->vRefNum;    /* Volume ID */
  1109.     myPB.dirInfo.ioDrParID=file->parID;        /* Initialize parent dir. */
  1110.     myPB.dirInfo.ioFDirIndex= -1;            /* <0: Use ioDrDirID as input. */
  1111.     myPB.dirInfo.ioCompletion=NULL;
  1112.     for(    myPB.dirInfo.ioDrDirID=file->parID; 
  1113.             myPB.dirInfo.ioDrDirID!=fsRtDirID;
  1114.             myPB.dirInfo.ioDrDirID=myPB.dirInfo.ioDrParID){
  1115.         myErr=PBGetCatInfo(&myPB, FALSE);
  1116.         if(myPB.dirInfo.ioResult==noErr){
  1117.             strcat(fullPath, ":");
  1118.             strcat(fullPath, PtoCstrPtr(dirName));
  1119.         }else
  1120.             break;
  1121.     }
  1122.     return fullPath;
  1123. }
  1124.  
  1125. /*----------------------------------------------------------------------------------
  1126.  * GetBaseName() - Converts a FSS file specification to a C string containing
  1127.  *                 the base file name, i.e., without the path.
  1128.  * The string the pointer points to is reused for each new call.
  1129.  *----------------------------------------------------------------------------------*/
  1130. char *GetBaseName(FSSpec *file){
  1131.     static char fullPath[100];                            /* Semi-permanent, reused. */
  1132.     
  1133.     strcpy(fullPath, PtoCstrPtr(file->name));            /* Add file name.  */
  1134.     return fullPath;                                    /* Return pointer. */
  1135. }
  1136.  
  1137. /*----------------------------------------------------------------------------------
  1138.  * GetFullPathName() - Converts a FSS file specification to a C string containing
  1139.  *                     the full path and the file name.
  1140.  *                     The string the pointer points to is reused for each new call.
  1141.  * See: New Inside Mac, "Files", p. 2-45: Constructing Full Pathnames, Listing 2-5.
  1142.  *----------------------------------------------------------------------------------*/
  1143. char *GetFullPathName(FSSpec *file){
  1144.     static char fullPath[1000];                            /* Semi-permanent, reused. */
  1145.     
  1146.     strcpy(fullPath, GetVolumeName(file));                /* Start with disk name. */
  1147.     strcat(fullPath, ":");                                /* Path always ends with colon. */
  1148.     GetFullPath(file->vRefNum, file->parID, fullPath);    /* Find full path. */
  1149.     strcat(fullPath, PtoCstrPtr(file->name));            /* Add file name.  */
  1150.     return fullPath;                                    /* Return pointer. */
  1151. }
  1152.  
  1153. /*----------------------------------------------------------------------------------
  1154.  * GetFullPath() - Returns full path name (without file name) in fullPath. Recursive.
  1155.  *
  1156.  * See: New Inside Mac, "Files", p. 2-45: Constructing Full Pathnames, Listing 2-5.
  1157.  * Because strcat() cannot handle overlapping strings, recursion is easier than
  1158.  * an iteration. The parts of the path are pasted together AFTER all parts are found. 
  1159.  *----------------------------------------------------------------------------------
  1160.  */
  1161. void GetFullPath(int VolumeSpec, long ParentDirID, char *fullPath){
  1162.     Str255         dirName;
  1163.     CInfoPBRec    myPB;
  1164.     OSErr        myErr;
  1165.  
  1166.     myPB.dirInfo.ioVRefNum=VolumeSpec;
  1167.     myPB.dirInfo.ioDrDirID=ParentDirID;
  1168.     myPB.dirInfo.ioFDirIndex= -1;            /* <0: Use ioDrDirID as input. */
  1169.     myPB.dirInfo.ioCompletion=NULL;
  1170.     myPB.dirInfo.ioNamePtr=dirName;            /* Output buffer for PBGetCatInfo(). */
  1171.     myErr=PBGetCatInfo(&myPB, FALSE);        /* receive parent dir in dirName */
  1172.     if(myErr==noErr){
  1173.         if(myPB.dirInfo.ioDrParID!=fsRtDirID)    /* This is the root dir ID. */
  1174.             GetFullPath(VolumeSpec, myPB.dirInfo.ioDrParID, fullPath); /* RECURSION */
  1175.         strcat(fullPath, PtoCstrPtr(dirName));     /* paste parent to ancestors */
  1176.         strcat(fullPath, ":");                    /* Path always ends with colon. */
  1177.     }
  1178.     return;
  1179. }
  1180.  
  1181. /*----------------------------------------------------------------------------------
  1182.  * FSSpecRoutinesAvail() - Returns true if the FSS functions are available.
  1183.  *----------------------------------------------------------------------------------
  1184.  */
  1185. int FSSpecRoutinesAvail(void){
  1186.     OSErr        myErr = !noErr;
  1187.     long        myFeature;
  1188.     int            avail=0;
  1189.     
  1190.     if(1/*gHasGestalt()*/){
  1191.         myErr=Gestalt(gestaltFSAttr, &myFeature);
  1192.         if(myErr==noErr && (myFeature & gestaltHasFSSpecCalls))
  1193.             avail=1;
  1194.         else
  1195.             Log("Gestalt error");
  1196.     }else
  1197.         Log("Gestalt is not available");
  1198.         
  1199.     if(avail)
  1200.         Log("FSS Routines Available");
  1201.         
  1202.     return avail;
  1203. }
  1204.  
  1205. /*----------------------------------------------------------------------------------
  1206.  * select_input_file() - Allows the user to select an input file with a standard dialog box.
  1207.  *                       If numTypes == -1, all file types are displayed.
  1208.  *                       Returns: pointer to FSS record, or NULL on error or cancel.
  1209.  * See: New Inside Mac, "Files", p. 1-19: Opening a File, Listing 1-6.
  1210.  *----------------------------------------------------------------------------------*/
  1211. FSSpec *select_input_file(const int numTypes, SFTypeList myTypes){
  1212.     static StandardFileReply myReply;
  1213.     OSErr myErr=noErr;
  1214.     
  1215.     StandardGetFile(NULL, numTypes, myTypes, &myReply);
  1216.     if(myReply.sfGood){
  1217.         char type[5];
  1218.         LtoCstr(myReply.sfType, type);
  1219.         sprintf(buf, "select_input_file: Type: %s", type); Log(buf);
  1220.         return &myReply.sfFile;
  1221.     }else
  1222.         return NULL;
  1223. }
  1224.  
  1225. /*----------------------------------------------------------------------------------
  1226.  * select_output_file() - Allows the user to select an output file with a standard dialog box.
  1227.  *                        Returns: pointer to FSS record, or NULL on error or cancel.
  1228.  *----------------------------------------------------------------------------------*/
  1229. FSSpec *select_output_file(const char *prompt, const char *defname){
  1230.     Str255 Pprompt, Pdefname;
  1231.     static StandardFileReply myReply;
  1232.     OSErr myErr=noErr;
  1233.     
  1234.     strcpy((char *)Pprompt, prompt); CtoPstr((char *)Pprompt);    
  1235.     strcpy((char *)Pdefname, defname); CtoPstr((char *)Pdefname);    
  1236.     /* The cursor is set to an I-beam to edit the file name in the 
  1237.      * dialog box. Reset it to the default arrow. */
  1238.     StandardPutFile(Pprompt, Pdefname, &myReply);
  1239.     InitCursor();
  1240.     if(myReply.sfGood){
  1241.         return &myReply.sfFile;
  1242.     }else
  1243.         return NULL;
  1244. }
  1245.  
  1246. /*----------------------------------------------------------------------------------
  1247.  * FinderInfo() - Test output of Finder Info of a file: creator, type...
  1248.  *----------------------------------------------------------------------------------*/
  1249. void FinderInfo(FSSpec *fs){
  1250.     OSErr        myErr;
  1251.     FInfo        fndrInfo;
  1252.     char        creator[5], type[5];
  1253.     
  1254.     myErr=FSpGetFInfo(fs, &fndrInfo);
  1255.     LtoCstr(fndrInfo.fdType, type);
  1256.     LtoCstr(fndrInfo.fdCreator, creator);
  1257.     
  1258.     Log("-------------------------");
  1259.     strcpy(buf, "Getting Finder Info: ");
  1260.     switch(myErr){
  1261.     case noErr:    strcat(buf, "No error"); break;
  1262.     case nsvErr:   strcat(buf, "No such volume"); break;
  1263.     case ioErr:    strcat(buf, "I/O error"); break;
  1264.     case bdNamErr: strcat(buf, "Bad filename"); break;
  1265.     case fnfErr:   strcat(buf, "File not found"); break;
  1266.     case paramErr: strcat(buf, "No default volume"); break;
  1267.     case dirNFErr: strcat(buf, "Directory not found or incomplete pathname"); break;
  1268.     case afpAccessDenied: strcat(buf, "User does not have the correct access"); break;
  1269.     case afpObjectTypeErr: strcat(buf, "Directory not found or incomplete pathname"); break;
  1270.     default :      strcat(buf, "Unknown error"); break;
  1271.     }
  1272.     Log(buf);
  1273.     if(myErr==noErr){
  1274.         sprintf(buf, "Type: '%s'  Creator: '%s', Flags: 0x%04X, Location: X=%d Y=%d, Directory: %d", 
  1275.                 type, creator,
  1276.                 fndrInfo.fdFlags, fndrInfo.fdLocation.h, fndrInfo.fdLocation.v,
  1277.                 fndrInfo.fdFldr); Log(buf);
  1278.     }
  1279.     return;
  1280. }
  1281.  
  1282. /*----------------------------------------------------------------------------------
  1283.  * PathInfo() - Test output with info on the PathID.
  1284.  *----------------------------------------------------------------------------------*/
  1285. void PathInfo(FSSpec *fs){
  1286.     CInfoPBRec    myPB;
  1287.     Str255         dirName;
  1288.     OSErr        myErr;
  1289.     
  1290.     myPB.dirInfo.ioNamePtr=dirName;            /* Output buffer for PBGetCatInfo(). */
  1291.     myPB.dirInfo.ioVRefNum=fs->vRefNum;    /* Volume ID */
  1292.     myPB.dirInfo.ioDrDirID=fs->parID; 
  1293.     myPB.dirInfo.ioFDirIndex= -1;            /* <0: Use ioDrDirID as input. */
  1294.  
  1295.     Log("-------------------------");
  1296.     myErr=PBGetCatInfo(&myPB, FALSE);
  1297.     sprintf(buf, "Getting Path Info: %s", myErr==noErr?"OK":"Error"); Log(buf);
  1298.     sprintf(buf, "ID of this dir:   %ld, Parent dir: \"%s\"", 
  1299.         myPB.dirInfo.ioDrDirID, PtoCstr(dirName)); Log(buf);
  1300.     sprintf(buf, "ID of parent dir: %ld, Files in dir:     %d", 
  1301.         myPB.dirInfo.ioDrParID,  myPB.dirInfo.ioDrNmFls); Log(buf);
  1302.  
  1303.     return;
  1304. }
  1305.  
  1306. /*----------------------------------------------------------------------------------
  1307.  * GetVolumeName() - Returns pointer to the volume name specified in fs.
  1308.  *----------------------------------------------------------------------------------*/
  1309. char *GetVolumeName(FSSpec *fs){
  1310.     static char        name[35]; /* Volume names are up to 27 chars. */
  1311.     HParamBlockRec     myHPB;
  1312.     OSErr             myErr;
  1313.  
  1314.     myHPB.volumeParam.ioNamePtr=(StringPtr)name;
  1315.     myHPB.volumeParam.ioVRefNum=fs->vRefNum;
  1316.     myHPB.volumeParam.ioVolIndex=0;
  1317.     myErr=PBHGetVInfo(&myHPB, FALSE);
  1318.     PtoCstr((StringPtr)name);
  1319.     return name;
  1320. }
  1321.  
  1322. /*----------------------------------------------------------------------------------
  1323.  * VolumeInfo() - Test output.
  1324.  *----------------------------------------------------------------------------------*/
  1325. void VolumeInfo(FSSpec *fs){
  1326.     HParamBlockRec     myHPB;
  1327.     OSErr             myErr;
  1328.     char            name[35]; /* Volume names are up to 27 chars. */
  1329.     long            bytes, MB=1024L*1024L;
  1330.             
  1331.     myHPB.volumeParam.ioNamePtr=(StringPtr)name;
  1332.     myHPB.volumeParam.ioVRefNum=fs->vRefNum;
  1333.     myHPB.volumeParam.ioVolIndex=0;
  1334.     myErr=PBHGetVInfo(&myHPB, FALSE);
  1335.     Log("-------------------------");
  1336.     sprintf(buf, "Getting Volume Info: %s", myErr==noErr?"OK":"Error"); Log(buf);
  1337.     sprintf(buf, "Drive Number: %d, Volume Specification Number: %d", 
  1338.             myHPB.volumeParam.ioVDrvInfo, myHPB.volumeParam.ioVRefNum); Log(buf);
  1339.     sprintf(buf, "Allocation Block Size: %ld bytes", myHPB.volumeParam.ioVAlBlkSiz); Log(buf);
  1340.     sprintf(buf, "Clump Size: %ld bytes", myHPB.volumeParam.ioVClpSiz); Log(buf);
  1341.     sprintf(buf, "Free: %d Allocation Blocks", myHPB.volumeParam.ioVFrBlk); Log(buf);
  1342.     bytes=myHPB.volumeParam.ioVFrBlk * myHPB.volumeParam.ioVAlBlkSiz;
  1343.     sprintf(buf, "Name: %s, Free: %ld bytes = %g MB", 
  1344.             PtoCstrPtr(myHPB.volumeParam.ioNamePtr), bytes, (float)bytes/MB); Log(buf);
  1345.     return;
  1346. }
  1347.  
  1348. /*----------------------------------------------------------------------------------
  1349.  * TestPathUtils()
  1350.  *----------------------------------------------------------------------------------*/
  1351. void TestPathUtils(void){
  1352.     
  1353.     FSSpecRoutinesAvail();
  1354.     
  1355.     /* Test of PtoCstrPtr(). */
  1356.     {
  1357.         char *str;
  1358.         Str255 Pstr="\pHello";
  1359.         
  1360.         str=PtoCstrPtr(Pstr);
  1361.         Log(str);
  1362.     }
  1363.     
  1364.     /* Test of select_input_file(). */
  1365.     {
  1366.         SFTypeList myTypes;
  1367.         FSSpec *fs;
  1368.     
  1369.         //myTypes[0]='TEXT';
  1370.         fs=select_input_file(-1, myTypes);
  1371.         if(fs==NULL){
  1372.             Log("Error select_input_file() or user cancelled");
  1373.             return;
  1374.         }
  1375.         FinderInfo(fs);
  1376.         VolumeInfo(fs);
  1377.         PathInfo(fs);
  1378.         
  1379.         if(fs){
  1380.             Log("-------------------------");
  1381.             Log("Getting full name");
  1382.             {
  1383.             char *fullname=FSStoCstrPtr(fs);
  1384.             sprintf(buf, "FSStoCstrPtr: %s", fullname);Log(buf);
  1385.             fullname=GetFullPathName(fs);
  1386.             sprintf(buf, "GetFullPathName: %s", fullname);Log(buf);
  1387.             }
  1388.             Log("-------------------------");
  1389.         }
  1390.     }
  1391.         
  1392.     return;
  1393. }
  1394.  
  1395. /*----------------------------------------------------------------------------------
  1396.  * macftype() - Changes the file type and creator if specified.
  1397.  *              Example: macftype(fss, 0L, 'TEXT');
  1398.  *----------------------------------------------------------------------------------*/
  1399. MacFILE *macftype(FSSpec *selection, long creator, long type){
  1400.     short vRefNum=selection->vRefNum;
  1401.     long  dirID  =selection->parID;
  1402.     Str255 fileName;
  1403.     FInfo fndrInfo;
  1404.     
  1405.     /* FSSpec.name is 63 byte string */
  1406.     memcpy(fileName, selection->name, sizeof(selection->name));
  1407.     
  1408.     HGetFInfo(vRefNum, dirID, fileName, &fndrInfo);
  1409.     
  1410.     if(creator) fndrInfo.fdCreator=creator;
  1411.     if(type)    fndrInfo.fdType   =type;
  1412.     
  1413.     HSetFInfo(vRefNum, dirID, fileName, &fndrInfo);
  1414.     
  1415.     return;
  1416. }
  1417.  
  1418. /*----------------------------------------------------------------------------------
  1419.  * macfopen() - Returns a pointer to an entry in the file table, or NULL on error.
  1420.  *----------------------------------------------------------------------------------*/
  1421. MacFILE *macfopen(FSSpec *selection, char *mode){
  1422.  
  1423.         /* This is the file table. */
  1424.     static MacFILE mac_file_table[FOPEN_MAX]; /* Like ANSI C */
  1425.     
  1426.     int         i;
  1427.     OSErr         myErr;
  1428.     SignedByte    permissions;
  1429.     
  1430.     if(selection==NULL) return;
  1431.     
  1432.     /* Find a free slot. */
  1433.     for(i=0; i<FOPEN_MAX && mac_file_table[i].in_use; i++);
  1434.     if(i==FOPEN_MAX)
  1435.         return NULL;
  1436.         
  1437.     /* Translate mode to permissions. */
  1438.     if(strchr(mode, 'w')){
  1439.         HParamBlockRec     myHPB;
  1440.         OSErr             myErr;
  1441.         long            bytes, MB=1024L*1024L;
  1442.             
  1443.         myHPB.volumeParam.ioNamePtr=NULL;
  1444.         myHPB.volumeParam.ioVRefNum=selection->vRefNum;
  1445.         myHPB.volumeParam.ioVolIndex=0;
  1446.         myErr=PBHGetVInfo(&myHPB, FALSE);
  1447.         /* Check if the volume is locked. FSpOpenDF() will still open the
  1448.          * file for write access, but writing will cause an error.
  1449.          * See New Inside Mac, "Files", p. 2-8.
  1450.          * It recommends calling PGHGetVInfo(), which is described at p. 2-144.
  1451.          * HOWEVER, I can't find the description for the 
  1452.          * volume attributes ioVAtrb ???
  1453.          */
  1454.         //if(myHPB.volumeParam.ioVAtrb & ????????)
  1455.         //    return NULL;
  1456.         permissions=fsRdWrPerm;
  1457.     }else
  1458.         permissions=fsRdPerm;
  1459.     
  1460.     /* Open it. If file-to-write not found, create it and try again. */
  1461.     myErr=FSpOpenDF(selection, permissions, &mac_file_table[i].refnum);
  1462.     
  1463.     if(myErr==fnfErr && permissions==fsRdWrPerm)
  1464.         if(noErr==FSpCreate(selection, CREATOR, 'TEXT', smSystemScript))
  1465.             myErr=FSpOpenDF(selection, permissions, &mac_file_table[i].refnum);
  1466.             
  1467.     if(myErr!=noErr)
  1468.         return NULL;
  1469.     
  1470.     mac_file_table[i].in_use=1;
  1471.     mac_file_table[i].byteorder=BigEndian; /* Assume it is a Mac type file. */
  1472.     
  1473.     memcpy(&mac_file_table[i].fss, selection, sizeof(FSSpec));
  1474.     
  1475.     return &mac_file_table[i];
  1476. }
  1477.  
  1478. /*----------------------------------------------------------------------------------
  1479.  * macfclose() - Closes the file and flushes the volume, or returns non-zero on error.
  1480.  *----------------------------------------------------------------------------------*/
  1481. int macfclose(MacFILE *fp){
  1482.     OSErr myErr;
  1483.     
  1484.     if(fp==NULL) return;
  1485.     
  1486.     myErr=FSClose(fp->refnum);
  1487.     if(myErr==noErr){
  1488.         FlushVol(NULL, fp->fss.vRefNum);
  1489.         return 0;
  1490.     }else
  1491.         return EOF;
  1492. }
  1493.  
  1494. /*----------------------------------------------------------------------------------
  1495.  * macfread() - Like fread().
  1496.  *----------------------------------------------------------------------------------*/
  1497. int macfread(void *buf, size_t recsize, size_t recnum, MacFILE *fp){
  1498.     OSErr myErr=noErr;
  1499.     long  count=recsize;
  1500.     int   rec;
  1501.     char *Buffer=buf;
  1502.     
  1503.     if(fp==NULL) return;
  1504.     
  1505.     /* Transfer data in the chunks as specified. */
  1506.     for(rec=0; rec<recnum && myErr==noErr; rec++){
  1507.         myErr=FSRead(fp->refnum, &count, Buffer);
  1508.         Buffer += count;
  1509.     }
  1510.     
  1511.     /* Count only records that transferred successfully. */
  1512.     if(myErr!=noErr)
  1513.         rec--;
  1514.     
  1515.     /* Return how many records transferred successfully. */
  1516.     return rec;
  1517. }
  1518.  
  1519. /*----------------------------------------------------------------------------------
  1520.  * macfwrite() - Like fwrite().
  1521.  *----------------------------------------------------------------------------------*/
  1522. int macfwrite(void *buf, size_t recsize, size_t recnum, MacFILE *fp){
  1523.     OSErr myErr=noErr;
  1524.     long  count=recsize;
  1525.     int   rec;
  1526.     char *Buffer=buf;
  1527.     
  1528.     if(fp==NULL) return;
  1529.     
  1530.     /* Transfer data in the chunks as specified. */
  1531.     for(rec=0; rec<recnum && myErr==noErr; rec++){
  1532.         myErr=FSWrite(fp->refnum, &count, Buffer);
  1533.         Buffer += count;
  1534.     }
  1535.     
  1536.     /* Count only records that transferred successfully. */
  1537.     if(myErr!=noErr)
  1538.         rec--;
  1539.     
  1540.     /* Return how many records transferred successfully. */
  1541.     return rec;
  1542. }
  1543.  
  1544. /*----------------------------------------------------------------------------------
  1545.  * TestFileType() - Determines what kind the open file is.
  1546.  *----------------------------------------------------------------------------------*/
  1547. int TestFileType(MacFILE *fp){
  1548.     char buf[100];
  1549.     int i, ctrl=0, bin=0, ret=0, nl=0, esc=0, Rochester=0, Hathaway=0, ps=0;
  1550.     
  1551.     if(fp==NULL) return;
  1552.     
  1553.     if(1==macfread(buf, sizeof(buf), 1, fp)){
  1554.         /* Test for headers. */
  1555.         if(!strncmp(buf, "%!", 2)) ps++;
  1556.         if(!strncmp(buf, "DSM version ", 12)) Hathaway++;
  1557.         /* Does the Rochester file have a header? */
  1558.         
  1559.         /* Test the bytes. */
  1560.         for(i=0; i<sizeof(buf); i++){
  1561.             switch(buf[i]){
  1562.             case '\r': ret++; break;
  1563.             case '\n': nl++; break;
  1564.             case 0x1B: esc++; break;
  1565.             case '\t': case '\f': case '\b': case '\v': break;
  1566.             default:
  1567.                 if(buf[i]<0x1f) ctrl++;
  1568.                 if(buf[i]>0x7f) bin++;
  1569.                 break;
  1570.             }
  1571.         }
  1572.     }
  1573.     
  1574.     sprintf(buf, "ctrl=%d, bin=%d, ret=%d, nl=%d, esc=%d", 
  1575.                   ctrl,    bin,    ret,    nl,    esc); Log(buf);
  1576.     if(Rochester) Log("Rochester Transient Fault Recorder file");
  1577.     if(Hathaway)  Log("Hathaway Digital Signal Monitor file");
  1578.     if(ps)        Log("PostScript file");
  1579.     if(bin) 
  1580.         Log("Binary file");
  1581.     else{
  1582.         if(!ret &&  nl) Log("Unix text file");
  1583.         if( ret && !nl) Log("Macintosh text file");
  1584.         if( ret &&  nl) Log("MS-DOS text file");
  1585.     }
  1586.     
  1587.     return 0;
  1588. }
  1589.  
  1590. /*----------------------------------------------------------------------------------
  1591.  * macfseek() - Like fseek().
  1592.  *----------------------------------------------------------------------------------*/
  1593. int macfseek(MacFILE *fp, long offset, int whence){
  1594.     OSErr myErr;
  1595.     short posMode;
  1596.  
  1597.     if(!fp) return -1;
  1598.     
  1599.     switch(whence){
  1600.     case SEEK_SET: posMode=fsFromStart; break;
  1601.     case SEEK_CUR: posMode=fsFromMark;  break;
  1602.     case SEEK_END: posMode=fsFromLEOF;  break;
  1603.     default: return -1; break;
  1604.     }
  1605.     
  1606.     myErr=SetFPos(fp->refnum, posMode, offset);
  1607.     
  1608.     return myErr==noErr?0:-1;
  1609. }
  1610.  
  1611. /*----------------------------------------------------------------------------------
  1612.  * macftell() - Like ftell().
  1613.  *----------------------------------------------------------------------------------*/
  1614. long macftell(MacFILE *fp){
  1615.     OSErr myErr;
  1616.     long offset;
  1617.  
  1618.     if(!fp) return -1;
  1619.     
  1620.     myErr=GetFPos(fp->refnum, &offset);
  1621.     if(myErr!=noErr) errno=1; /* Required by ANSI C standard. */
  1622.     
  1623.     return myErr==noErr?offset:-1L;
  1624. }
  1625.  
  1626. /*----------------------------------------------------------------------------------
  1627.  * macfstat() - Get file status. Returns zero on success, or -1 on error.
  1628.  *              Not all unix features are implemented yet.
  1629.  *----------------------------------------------------------------------------------*/
  1630. int macfstat(MacFILE *fp, struct MacStat *buf){
  1631.     static char        name[35]; /* Volume names are up to 27 chars. */
  1632.     HParamBlockRec     myHPB; /* New Ins.Mac, `Files', p. 2-269 */
  1633.     OSErr             myErr;
  1634.     DateTimeRec        date;
  1635.  
  1636.     if(!buf) return -1;
  1637.     
  1638.     myHPB.volumeParam.ioCompletion=0;
  1639.     myHPB.volumeParam.ioNamePtr=(StringPtr)fp->fss.name;
  1640.     myHPB.volumeParam.ioVRefNum=fp->fss.vRefNum;
  1641.     myHPB.fileParam.ioFDirIndex=0;
  1642.     myHPB.fileParam.ioDirID=fp->fss.parID;
  1643.     myErr=PBHGetFInfo(&myHPB, FALSE); /* New Ins.Mac, `Files', p. 2-194 */
  1644.     
  1645.     Secs2Date(myHPB.fileParam.ioFlMdDat, &date);
  1646.     buf->year=date.year;
  1647.     
  1648.     return myErr==noErr?0:-1;
  1649. }
  1650.  
  1651. /*----------------------------------------------------------------------------------
  1652.  * copy_file() - For testing.
  1653.  *----------------------------------------------------------------------------------*/
  1654. void copy_file(MacFILE *fp_in, MacFILE *fp_out){
  1655. #define recsiz 100
  1656.     char rec[recsiz];
  1657.     int  irec, nrec, lrec;
  1658.     long fsiz;
  1659.     
  1660.     if(!fp_in || !fp_out) return;
  1661.     
  1662.     /* File size. */
  1663.     macfseek(fp_in,  0L, SEEK_END);
  1664.     fsiz=macftell(fp_in);
  1665.     nrec=fsiz/recsiz;
  1666.     lrec=fsiz-(nrec*recsiz); /* Size of last, partial, record. */
  1667.     macfseek(fp_in,  0L, SEEK_SET);
  1668.     macfseek(fp_out, 0L, SEEK_SET);
  1669.     sprintf(buf, "File size: %ld bytes = %d chunks of %d bytes plus one of %d bytes",
  1670.                             fsiz,      nrec,      recsiz,                lrec); Log(buf);
  1671.     
  1672.     /* Transfer full records. */
  1673.     for(irec=0; irec<nrec; irec++){
  1674.         if(1!=macfread (rec, recsiz, 1, fp_in)) break;
  1675.         if(1!=macfwrite(rec, recsiz, 1, fp_out)) break;
  1676.     }
  1677.     
  1678.     /* Transfer the last, partial record. */
  1679.     if(lrec && 1==macfread(rec, lrec, 1, fp_in))
  1680.         macfwrite(rec, lrec, 1, fp_out);
  1681.     
  1682.     Log("Copy Done.");    
  1683.     return;
  1684. }
  1685.  
  1686. /*----------------------------------------------------------------------------------
  1687.  * TestFileUtils()
  1688.  *----------------------------------------------------------------------------------*/
  1689. void TestFileUtils(void){
  1690.     MacFILE *fp_in, *fp_out;
  1691.     FSSpec  *fs_in, *fs_out;
  1692.     SFTypeList             myTypes;
  1693.     StandardFileReply     myReply;
  1694.     
  1695.     Log("Testing the file utility functions");
  1696.     
  1697.     fs_in=select_input_file(-1, myTypes); /* Input file */
  1698.     fp_in=macfopen(fs_in, "r");
  1699.     
  1700.     TestFileType(fp_in);
  1701.     
  1702.     StandardPutFile("\pFormat: see diagnostic window", "\pdummy", &myReply);
  1703.     fs_out=myReply.sfGood?&myReply.sfFile:NULL;
  1704.     fp_out=macfopen(fs_out, "w");
  1705.     
  1706.     copy_file(fp_in, fp_out);
  1707.     
  1708.     macfclose(fp_in);
  1709.     macfclose(fp_out);
  1710.     
  1711.     return;
  1712. }
  1713.  
  1714. /*----------------------------------------------------------------------------------
  1715.  * BetterMoveWindow() - Moves the window partially down and to the right with 
  1716.  *                      amounts between 0 and 1, where the entire screen size is one.
  1717.  *  The window will not get too close to the border.
  1718.  *----------------------------------------------------------------------------------*/
  1719. void BetterMoveWindow(WindowPtr wp, float right, float down){
  1720.     Rect r;
  1721.     short h, w, x, y;
  1722.     
  1723.     /* Move the box to the center of the screen, horizontally, and
  1724.      * one-third down, but not too close to the border.
  1725.      * This is difficult to do with RezEdit. 
  1726.      */
  1727.     r=wp->portRect;
  1728.     h=r.bottom-r.top; /* height */
  1729.     w=r.right-r.left; /* width */
  1730.     x=(screenBits.bounds.right-w) * right;
  1731.     if(x<10) x=10;
  1732.     y=(screenBits.bounds.bottom-30-h) * down +30; /* Menubar is 30 pixels high. */
  1733.     if(y<30) y=30;
  1734.     MoveWindow(wp, x, y, TRUE);
  1735. }
  1736.  
  1737.  
  1738. /*----------------------------------------------------------------------------------
  1739.  * SwapN() - swaps n bytes of buf in place, also convert IEEE 8-byte double to 
  1740.  *           Macintosh double (12-byte)
  1741.  *----------------------------------------------------------------------------------*/
  1742. void SwapN(void *buf, int n){
  1743.     char c, *b, *e;
  1744.     for(b=buf, e=b+n-1; b<e; b++, e--){
  1745.          c = *b;
  1746.         *b = *e;
  1747.         *e =  c;
  1748.     }    
  1749.     return;
  1750. }
  1751.  
  1752. /*----------------------------------------------------------------------------------
  1753.  * NeedSwap() - swaps n bytes of buf in place, also convert IEEE 8-byte double to 
  1754.  *           Macintosh double (12-byte), BUT ONLY IF NEEDED, i.e., if the byte 
  1755.  *              order of the CPU running this program is different from the file type.
  1756.  * Returns: True if swap was needed.
  1757.  *----------------------------------------------------------------------------------*/
  1758. int NeedSwap(MacFILE *fp, void *buf, int n){
  1759.     if(computerbyteorder != fp->byteorder){
  1760.         SwapN(buf, n);
  1761.         return 1;
  1762.     }else
  1763.         return 0;
  1764. }
  1765.  
  1766. /*==================== INPUT FUNCTIONS =================*/
  1767.  
  1768. char GetInputByte(File *fp){
  1769.     char buf;
  1770.     long size=sizeof(buf);
  1771.     FileRead(&buf, size, 1, fp);
  1772.     return buf;
  1773. }
  1774.  
  1775. int GetInputInt(File *fp){
  1776.     int buf;
  1777.     long size=sizeof(buf);
  1778.     FileRead((char *)&buf, size, 1, fp);
  1779.     NeedSwap(fp, &buf, sizeof(buf));
  1780.     return buf;
  1781. }
  1782.  
  1783. long GetInputLong(File *fp){
  1784.     long buf;
  1785.     long size=sizeof(buf);
  1786.     FileRead((char *)&buf, size, 1, fp);
  1787.     NeedSwap(fp, &buf, sizeof(buf));
  1788.     return buf;
  1789. }
  1790.  
  1791. unsigned long GetInputULong(File *fp){
  1792.     unsigned long buf;
  1793.     long size=sizeof(buf);
  1794.     FileRead((char *)&buf, size, 1, fp);
  1795.     NeedSwap(fp, &buf, sizeof(buf));
  1796.     return buf;
  1797. }
  1798.  
  1799. float GetInputFloat(File *fp){
  1800.     float buf;
  1801.     long size=sizeof(buf);
  1802.     FileRead((char *)&buf, size, 1, fp);
  1803.     NeedSwap(fp, &buf, sizeof(buf));
  1804.     return buf;
  1805. }
  1806.  
  1807. /*
  1808. Note: make sure to use the 8-byte IEEE-compatible short double on the Mac
  1809. and not one of the Mac native 80 or 96 bit (10 or 12 byte) formats. 
  1810. */
  1811. double GetInputDouble(File *fp){
  1812.     double retval;
  1813. #ifdef THINK_C
  1814.     short double buf; /* IEEE-compatible 8-byte floating point on Mac. */
  1815. #else
  1816.     double buf;
  1817. #endif
  1818.     long size=sizeof(buf);
  1819.     FileRead((char *)&buf, size, 1, fp);
  1820.     NeedSwap(fp, &buf, sizeof(buf));
  1821.     retval=buf; /* Convert to Mac native format. */
  1822.     return retval;
  1823. }
  1824.  
  1825. char *GetInputString(char *str, int len, File *fp){
  1826.     int i, itemsread;
  1827.     char buf;    
  1828.     long size=sizeof(buf);
  1829.     
  1830.     for(i=0; i<len && buf && itemsread; i++){
  1831.         itemsread=FileRead((char *)&buf, size, 1, fp);
  1832.         *str=buf;
  1833.         str++;
  1834.     }
  1835.     
  1836.     *str='\0';
  1837.         
  1838.     return str;
  1839. }
  1840.  
  1841. char *GetInputNString(char *str, int len, File *fp){
  1842.     int itemsread;
  1843.     
  1844.     itemsread=FileRead(str, 1, len, fp);
  1845.     if(str[itemsread-1]!='\0')
  1846.         str[itemsread]='\0';
  1847.         
  1848.     return str;
  1849. }
  1850.  
  1851. /*==================== OUTPUT FUNCTIONS =================*/
  1852.  
  1853. // Writes a C string to the output file.
  1854. int WriteTxt(File *fp, char *str){
  1855.     return FWRITE(str, strlen(str), 1, fp);
  1856. }
  1857.  
  1858. // Writes bytes to a binary output file.
  1859. int WriteBin(File *fp, void *buf, int size){
  1860.     return FWRITE(buf, size, 1, fp);
  1861. }
  1862.  
  1863. void WriteULong(File *fp, unsigned long x){
  1864.     unsigned long buf;                // copy the data x, it may be a constant
  1865.     buf=x;
  1866.     NeedSwap(fp, &buf, sizeof(buf));
  1867.     WriteBin(fp, &buf, sizeof buf);
  1868. }
  1869.  
  1870. void WriteLong(File *fp, long x){
  1871.     long buf;
  1872.     buf=x;
  1873.     NeedSwap(fp, &buf, sizeof(buf));
  1874.     WriteBin(fp, &buf, sizeof buf);
  1875. }
  1876.  
  1877. void WriteShort(File *fp, signed short x){
  1878.     signed short buf;
  1879.     buf=x;
  1880.     NeedSwap(fp, &buf, sizeof(buf));
  1881.     WriteBin(fp, &buf, sizeof buf);
  1882. }
  1883.  
  1884. ---------------------------
  1885.  
  1886. >From reinder@neuretp.biol.ruu.nl (Reinder Verlinde)
  1887. Subject: How to detect whether Debugger is installed?
  1888. Date: Mon, 11 Jul 1994 12:10:44 GMT
  1889. Organization: Rijksuniversiteit Utrecht
  1890.  
  1891. The subject says it all: How do you detect whether MacsBug is present?
  1892. I want to know this since I have this FKEY which should activate
  1893. MacsBug,
  1894. and not do anything when MacsBug is not present. The usual
  1895. TrapAvailable
  1896. method does not seem to work since
  1897.  
  1898.   GetTrapAddress( _Unimplemented) == GetTrapAddress( _Debugger)
  1899.  
  1900. irrespective of the presence of MacsBug. I also looked up the Gestalt
  1901. selectors, and there is one to check whether the Debugger Utilities are
  1902. present, but I can't find one to check the presence of the Debugger.
  1903.  
  1904. I can think of numerous imperfect ways to check this (comparing first
  1905. bytes of _Unimplemented with a copy in my code, checking for MacsBug in
  1906. the System Folder, etcetera), but there should be a perfect way.
  1907.  
  1908. reinder@neuretp.biol.ruu.nl (Reinder Verlinde)
  1909.  
  1910. +++++++++++++++++++++++++++
  1911.  
  1912. >From busfield@hurricane.seas.ucla.edu (John D. Busfield)
  1913. Date: Wed, 13 Jul 1994 16:14:40 GMT
  1914. Organization: School of Engineering & Applied Science, UCLA.
  1915.  
  1916. In <1994Jul11.121044.4311@cc.ruu.nl> reinder@neuretp.biol.ruu.nl (Reinder Verlinde) writes:
  1917.  
  1918. >The subject says it all: How do you detect whether MacsBug is present?
  1919. >I want to know this since I have this FKEY which should activate
  1920. >MacsBug,
  1921. >and not do anything when MacsBug is not present.
  1922.  
  1923. Here's what it says in Macsbug Reference and Debugging Guide pg 412
  1924.  
  1925. How MacsBug installs itself.
  1926.  
  1927. When a system error or 68000 exception occurs, the ROM code examines
  1928. the global variable MacJmp to obtain the address of the debuggers entry
  1929. point. MacJmp might contain additional information, depending on whether you
  1930. are running under a 24-bit or 32-bit Memory Manager.
  1931.  
  1932. If you are running under a 24-bit Memory Manager, the high-order byte
  1933. of MacJmp is a flags byte that contains the following information.
  1934.  
  1935. Bit        Meaning
  1936. 7        Set if debugger is running
  1937. 6        Set if debugger can handle system errors
  1938. 5        Set if debugger is installed
  1939. 4        Set if debugger can support the Discipline utility
  1940.  
  1941. The lower 3 bytes of MacJmp are used to store the address of the debugger's 
  1942. entry point.
  1943.  
  1944. If you are running under a 32-bit Memory Manager, the flags byte is
  1945. moved to address $BFF and the long word at MacJmp becomes a full 32-bit
  1946. address that points to the debugger's entry point.
  1947.  
  1948. So to answer your question, you should only need to look at bit 5 of
  1949. the flags byte.
  1950.  
  1951. -- 
  1952. - ----------------------------------------------------------------------------
  1953. John Busfield                | All my realities are virtual
  1954. busfield@hurricane.seas.ucla.edu
  1955. _____________________________________________________________________________
  1956.  
  1957. +++++++++++++++++++++++++++
  1958.  
  1959. >From dlamkins@tiac.net (David B. Lamkins)
  1960. Date: 17 Jul 1994 00:48:29 GMT
  1961. Organization: DBL Systems
  1962.  
  1963. In article <1994Jul11.121044.4311@cc.ruu.nl>
  1964. reinder@neuretp.biol.ruu.nl (Reinder Verlinde) writes:
  1965.  
  1966. > The subject says it all: How do you detect whether MacsBug is present?
  1967.  
  1968. The following Pascal unit does everything you need (except give you C
  1969. code.)  The Apple manual doesn't tell the entire story -- the comments
  1970. in the code tell which debuggers and system patches break the rules.
  1971.  
  1972. unit DebuggerTest;
  1973.  
  1974. interface
  1975.  
  1976.     type
  1977.         DebuggerKind = ( {}
  1978.             debuggerKindNone, {}
  1979.             debuggerKindMacsBug, {}
  1980.             debuggerKindTMON, {}
  1981.             debuggerKindJasik, {}
  1982.             debuggerKindABZmon, {}
  1983.             debuggerKindOther {}
  1984.             );
  1985.         DebuggerSignature = packed array[1..2] of Char;
  1986.  
  1987. {$IFC (UNDEFINED DebuggerTest_Signature) | DebuggerTest_Signature}
  1988.     procedure GetDebuggerInfo (var present, active: Boolean; var kind:
  1989. DebuggerKind; var signature: DebuggerSignature);
  1990. {$ENDC}
  1991.  
  1992. {ABZmon can load Òon top ofÓ another debugger. In this case, the
  1993. underlying debugger}
  1994. {becomes the secondary debugger, but is the only one reported by
  1995. GetDebuggerInfo, which}
  1996. {looks in the ÒnormalÓ places before trying to find ABZmon. The
  1997. ABZMonIsLoaded function}
  1998. {can be used to detect ABZmonÕs presence when not the only debugger.}
  1999.     function ABZMonIsLoaded: Boolean;
  2000.  
  2001.     function DebuggerPresent: Boolean;
  2002.  
  2003. implementation
  2004.  
  2005.     function ValidDebuggerWorldAddress (p: univ Ptr): Boolean;
  2006.     begin
  2007.     {Address must be even and somewhere within addressable RAM or ROM.}
  2008.         ValidDebuggerWorldAddress := not ODD(ORD(p)) and (ORD(p) >= 0) and
  2009. (ORD(p) < ORD(MFTopMem));
  2010.     end;
  2011.  
  2012.     type
  2013.         LongPtr = ^Longint;
  2014.         IntPtr = ^Integer;
  2015.         PtrPtr = ^Ptr;
  2016.  
  2017.     function GetVBR: Ptr;
  2018.     inline
  2019.         $7008,             {MOVEQ #$EnterSupervisorMode,D0}
  2020.         $A08D,            {_DebugUtil}
  2021.         $4E7A, $8801,    {MOVEC VBR,A0}
  2022.         $46C0,            {MOVE D0,SR    ;restore user mode}
  2023.         $2E88;            {MOVE.L A0,(A7)}
  2024.  
  2025.     function ABZMonIsLoaded: Boolean;
  2026.         const
  2027.             _DebugUtil = $A08D;
  2028.             _Unimplemented = $A89F;
  2029.         var
  2030.             VBR: Ptr;
  2031.             vectorPtr: PtrPtr;
  2032.             codePtr: LongPtr;
  2033.             err: OSErr;
  2034.     begin
  2035.     {Alain BirtzÕs ABZmon doesnÕt use MacJmp at all. In fact, it doesnÕt
  2036. even use}
  2037.     {the trap dispatcher table. Instead, it patches the trap dispatcher!
  2038. The hint for}
  2039.     {finding this, aside from not finding it anywhere else, is that ABZmon
  2040. defines}
  2041.     {a private trap _DebugNum $AAFF - this has reserved bit 9 set.
  2042. ABZmonÕs trap}
  2043.     {dispatcher can be identified by its first instruction, ORI #$700,SR.
  2044. In hex, this}
  2045.     {is $007C0700.}
  2046.         if GetOSTrapAddress(_DebugUtil) = GetToolTrapAddress(_Unimplemented)
  2047. then
  2048.             VBR := Ptr(0)
  2049.         else
  2050.             begin
  2051.                 if DebuggerGetMax >= 8 then
  2052.                     VBR := GetVBR
  2053.                 else
  2054.                     VBR := Ptr(0);
  2055.             end;
  2056.         if ValidDebuggerWorldAddress(VBR) then
  2057.             begin
  2058.                 vectorPtr := PtrPtr(ORD(VBR) + $28);
  2059.                 codePtr := LongPtr(vectorPtr^);
  2060.                 ABZMonIsLoaded := ValidDebuggerWorldAddress(codePtr) & (codePtr^ =
  2061. $007C0700);
  2062.             end
  2063.         else
  2064.             ABZMonIsLoaded := False;
  2065.     end;
  2066.  
  2067. {$IFC (UNDEFINED DebuggerTest_Signature) | DebuggerTest_Signature}
  2068.     function NonStandardDebuggerKind (entry: univ Ptr): DebuggerKind;
  2069.     begin
  2070.         NonStandardDebuggerKind := debuggerKindOther;    {If we canÕt decideÉ}
  2071.  
  2072.     {JasikÕs ÒThe DebuggerÓ doesnÕt have a world pointer. Its
  2073. distinguishing}
  2074.     {feature is a test for whether it was entered via an F-line trap, by
  2075. executing}
  2076.     {the instruction CMPI #10,DSErrCode. In hex this is $0C7800100AF0.}
  2077.         if (LongPtr(entry)^ = $0C780010) and (IntPtr(ORD(entry) +
  2078. SIZEOF(Longint))^ = $0AF0) then
  2079.             NonStandardDebuggerKind := debuggerKindJasik
  2080.         else
  2081.  
  2082.     {Add other tests as needed.}
  2083.             ;
  2084.     end;
  2085. {$ENDC}
  2086.  
  2087. {This is based on info from ÒMacsBug Reference and Debugging Guide for
  2088. MacsBug version 6.2Ó}
  2089. {The MacsBug reference doesnÕt mention that the ROM debugger
  2090. masquerades as a real debugger.}
  2091. {Because the ROM debugger doesnÕt have a ÒworldÓ pointer, we have to do
  2092. some extra checks.}
  2093.     procedure GetDebuggerInfo (var present, active: Boolean; var kind:
  2094. DebuggerKind; var signature: DebuggerSignature);
  2095.         const
  2096.     {The first and current universal ROM is rev 1660. Assume}
  2097.     {that future universal ROMs will have higher rev numbers.}
  2098.             UnivROMVersion = 1660;
  2099.             MacJmp = $120;
  2100.             Debug32Flags = $BFF;
  2101.             ROMBase = $2AE;
  2102.             DebugInstalledFlagBit = 5;
  2103.             DebugActiveFlagBit = 7;
  2104.             Megabyte = $100000;
  2105.     {The following gestalt selectors are from Rene G.A. RosÕ SGSL.}
  2106.             gestaltEnablerAttr = 'bugy'; {32-bit System Enabler [1.0]}
  2107.             gestaltEnabler32bit = 7; {32-bit enabler present}
  2108.         type
  2109.             PtrPtr = ^Ptr;
  2110.             IntPtr = ^Integer;
  2111.             SigPtr = ^DebuggerSignature;
  2112.         var
  2113.             err: OSErr;
  2114.             gestaltResult: Longint;
  2115.             MM32Bit, univROM, apple32BitEnabler, broken: Boolean;
  2116.             debugFlagsAddr: Ptr;
  2117.             debugEntryAddr, debugWorldAddr, ROMBaseAddr: Ptr;
  2118.     begin
  2119.         err := Gestalt(gestaltAddressingModeAttr, gestaltResult);
  2120.         MM32Bit := (err = noErr) & BTST(gestaltResult,
  2121. gestalt32BitAddressing);
  2122.         err := Gestalt(gestaltROMVersion, gestaltResult);
  2123.         UnivROM := (err = noErr) & (gestaltResult >= UnivROMVersion);
  2124.         err := Gestalt(gestaltEnablerAttr, gestaltResult);
  2125.         apple32BitEnabler := (err = noErr) & BTST(gestaltResult,
  2126. gestaltEnabler32bit);
  2127.     {According to the reference, debugger flags are located in the high
  2128. byte of}
  2129.     {MacJmp unless the machine is 32-bit capable, in which case they move
  2130. to}
  2131.     {$BFF. IÕm not sure I believe that the 32-bit enablers (ConnectixÕs
  2132. MODE32}
  2133.     {and AppleÕs 32-bit System Enabler) report the right thing w.r.t.
  2134. 32-bit capability.}
  2135.     {Clearly, if the machine is running in 32-bit mode, itÕs 32-bit
  2136. capable even under}
  2137.     {the enablers. But when running under a 32-bit enabler in 24-bit mode,
  2138. the enabler}
  2139.     {would seem to be obliged to report 32-bit capability. In this state,
  2140. I wouldnÕt expect}
  2141.     {the enabler to put up enough of a charade to move the debugger flags
  2142. Ñ theyÕd almost}
  2143.     {certainly end up in the high byte of MacJmp. Also, AppleÕs enabler is
  2144. damaged in}
  2145.     {the opposite case Ñ the debugger traps still look at the high byte of
  2146. MacJmp even in}
  2147.     {32-bit mode. This requires a special test to pretend thereÕs no
  2148. debugger present under}
  2149.     {AppleÕs 32-bit System Enabler in 32-bit addressing mode; 24-bit mode
  2150. is OK.}
  2151.         broken := apple32BitEnabler and MM32Bit;
  2152.         if not broken then
  2153.             begin
  2154.                 if MM32Bit or UnivROM then
  2155.                     debugFlagsAddr := Ptr(Debug32Flags)
  2156.                 else
  2157.                     debugFlagsAddr := Ptr(MacJmp);
  2158.                 present := BTST(debugFlagsAddr^, DebugInstalledFlagBit);
  2159.                 active := BTST(debugFlagsAddr^, DebugActiveFlagBit);
  2160.             end
  2161.         else
  2162.             begin
  2163.                 present := False;
  2164.                 active := False;
  2165.             end;
  2166.         if present then
  2167.             begin
  2168.                 debugEntryAddr := StripAddress(PtrPtr(MacJmp)^);
  2169.                 ROMBaseAddr := StripAddress(PtrPtr(ROMBase)^);
  2170.                 if ORD(debugEntryAddr) > ORD(ROMBaseAddr) then    {Could be the ROM
  2171. debuggerÉ}
  2172.                     if MM32Bit then
  2173.                         begin    {In 32-bit mode, any address in or beyond ROM is not in
  2174. RAM.}
  2175.                             present := False;
  2176.                             Exit(GetDebuggerInfo);
  2177.                         end
  2178.                     else if ORD(debugEntryAddr) <= ORD(ROMBaseAddr) + Megabyte then
  2179.                         begin    {In 24-bit mode, the ROM gets 1MB and can be followed by
  2180. RAM.}
  2181.                             present := False;
  2182.                             Exit(GetDebuggerInfo);
  2183.                         end;
  2184. {$IFC (UNDEFINED DebuggerTest_Signature) | DebuggerTest_Signature}
  2185.                 debugWorldAddr := PtrPtr(ORD(debugEntryAddr) - SIZEOF(Ptr))^;
  2186.                 if ValidDebuggerWorldAddress(debugWorldAddr) then
  2187.                     signature := SigPtr(debugWorldAddr)^
  2188.                 else
  2189.                     signature := '??';
  2190.                 case Integer(signature) of
  2191.                     $4D54:     {MT}
  2192.                         kind := debuggerKindMacsBug;
  2193.         {¥ This is from memory; I _think_ TMON registers itself this wayÉ}
  2194.                     $5748:     {WH}
  2195.                         kind := debuggerKindTMON;
  2196.                     otherwise
  2197.                         kind := NonStandardDebuggerKind(debugEntryAddr);
  2198.                 end;
  2199. {$ENDC}
  2200.             end
  2201.     {Alain BirtzÕs ABZmon doesnÕt put anything in MacJmp, but patches the
  2202. trap dispatcher.}
  2203.         else if ABZMonIsLoaded then
  2204.             begin
  2205.                 kind := debuggerKindABZmon;
  2206. {$IFC (UNDEFINED DebuggerTest_Signature) | DebuggerTest_Signature}
  2207.                 signature := '??';
  2208. {$ENDC}
  2209.                 present := True;
  2210.             end
  2211.         else    {No debugger present.}
  2212.             begin
  2213.                 kind := debuggerKindNone;
  2214. {$IFC (UNDEFINED DebuggerTest_Signature) | DebuggerTest_Signature}
  2215.                 signature := '  ';
  2216. {$ENDC}
  2217.             end;
  2218.     end;
  2219.  
  2220.     function DebuggerPresent: Boolean;
  2221.         var
  2222.             present, active: Boolean;
  2223.             kind: DebuggerKind;                {this never gets a value}
  2224.             signature: DebuggerSignature;    {this never gets a value}
  2225.     begin
  2226.         GetDebuggerInfo(present, active, kind, signature);
  2227.         DebuggerPresent := present;
  2228.     end;
  2229.  
  2230. end.
  2231.  
  2232. Dave
  2233. - --
  2234. CPU Cycles: Use them now or lose them forever...
  2235.  
  2236. ---------------------------
  2237.  
  2238. >From bb@lightside.com (Bob Bradley)
  2239. Subject: Q: Converting PB to FSSpec
  2240. Date: Fri, 22 Jul 1994 08:56:47 -0800
  2241. Organization: SS Software Inc.
  2242.  
  2243. I'm writing an application that needs to process all files/folders in a
  2244. folder/disk.
  2245.  
  2246. I have this much so far (hasn't been tested) that I've mostly copied &
  2247. modified from DragonSmith and DropShell 2.0 to make them work FSSpec's:
  2248.  
  2249. OSErr FSpProcessDirectoryContents( FSSpec *directory, FSSpecList fileList, 
  2250.                                    Boolean addDirectories, 
  2251.                                    Boolean lookInsideDirectories, 
  2252.                                    Boolean skipOnError )
  2253. {  
  2254.    OSErr            error = noErr;
  2255.    CInfoPBRec       pb;
  2256.    short            i;
  2257.    Str63            name;
  2258.    Boolean          keepGoing;
  2259.    long             directoryID;
  2260.    FSSpec           file;
  2261.    
  2262.    error = FSpGetDirectoryID( directory, &directoryID );
  2263.    if( error != noErr ) return( error );
  2264.    pb.hFileInfo.ioCompletion = NULL;
  2265.    pb.hFileInfo.ioNamePtr = &name[0];
  2266.    for( i = 1, keepGoing = TRUE; keepGoing; i++ )
  2267.    {
  2268.       pb.hFileInfo.ioVRefNum = directory->vRefNum;
  2269.       pb.hFileInfo.ioDirID = directoryID;
  2270.       pb.hFileInfo.ioFDirIndex = i;
  2271.       error = PBGetCatInfoSync( &pb );
  2272.       if( error == noErr )
  2273.       {
  2274.  
  2275.            // Right here I need something to convert the parameter block to
  2276.            // an FSSpec for this item in the directory. So I can pass it
  2277.            // my routine that either adds it to the FSSpec List (if it's a
  2278.            // file) or calls this routine again (if it's a folder).
  2279.  
  2280.       }
  2281.       else if( error == fnfErr || !skipOnError )
  2282.       {
  2283.          keepGoing = FALSE;
  2284.       }
  2285.    }
  2286.    if( error == fnfErr ) error = noErr;
  2287.    return( error );
  2288. }
  2289.  
  2290. Can I just copy the pb->h.fileParam.ioNamePtr, pb->c.hFileInfo.ioFlParID,
  2291. and pb.hFileInfo.ioVRefNum fields of the parameter block to the the
  2292. FSSpec? or do I need to do some other stuff? Do I need to any special
  2293. handling of alias's?
  2294.  
  2295. If you find errors in the above routine, I'd like to know about that too.
  2296.  
  2297. +++++++++++++++++++++++++++
  2298.  
  2299. >From woody@alumni.caltech.edu (William Edward Woody)
  2300. Date: 24 Jul 1994 19:37:26 GMT
  2301. Organization: California Institute of Technology, Alumni Association
  2302.  
  2303. >   FSSpec           file;
  2304. >   
  2305. >   error = FSpGetDirectoryID( directory, &directoryID );
  2306. >   if( error != noErr ) return( error );
  2307. >   pb.hFileInfo.ioCompletion = NULL;
  2308. >   pb.hFileInfo.ioNamePtr = &name[0];
  2309. >   for( i = 1, keepGoing = TRUE; keepGoing; i++ )
  2310. >   {
  2311. >      pb.hFileInfo.ioVRefNum = directory->vRefNum;
  2312. >      pb.hFileInfo.ioDirID = directoryID;
  2313. >      pb.hFileInfo.ioFDirIndex = i;
  2314. >      error = PBGetCatInfoSync( &pb );
  2315. >      if( error == noErr )
  2316. >      {
  2317. >
  2318. >           // Right here I need something to convert the parameter block to
  2319. >           // an FSSpec for this item in the directory. So I can pass it
  2320. >           // my routine that either adds it to the FSSpec List (if it's a
  2321.         /*
  2322.          *  Then there's my favorite way to do this
  2323.          */
  2324.  
  2325.         FSMakeFSSpec(directory->vRefNum,directoryID,pb.hFIleInfo.ioNamePtr,&file);
  2326.  
  2327.         /*
  2328.          *  Or something like that, your milege may vary.
  2329.          */
  2330.  
  2331. >           // file) or calls this routine again (if it's a folder).
  2332. >
  2333. >      }
  2334.  
  2335. I hope this helps.
  2336.  
  2337. Like Apple says: Don't build the FSSpec by hand yourself. Instead,
  2338. use FSMakeFSSpec() [IM VI Ch 25, pg 30] to do the dirty work.
  2339.  
  2340.                     - Bill
  2341. -- 
  2342. - William Edward Woody                  | Disclamer:
  2343.   woody@alumni.cco.caltech.edu             | "He who knows does not speak;
  2344. - In Phase Consulting                   |  He who speaks does not know."
  2345.   337 West California #4; Glendale, CA 91203 |            - Lao Tzu
  2346.  
  2347. +++++++++++++++++++++++++++
  2348.  
  2349. >From mclow@san_marcos.csusm.edu (Marshall Clow)
  2350. Date: Sat, 23 Jul 1994 15:40:48 -0800
  2351. Organization: Aladdin Systems
  2352.  
  2353. In article <bb-2207940856470001@user59.lightside.com>, bb@lightside.com
  2354. (Bob Bradley) wrote:
  2355.  
  2356. > I'm writing an application that needs to process all files/folders in a
  2357. > folder/disk.
  2358. > I have this much so far (hasn't been tested) that I've mostly copied &
  2359. > modified from DragonSmith and DropShell 2.0 to make them work FSSpec's:
  2360.    I always like to see people using DropShell! I will admit to being a
  2361. little confused, though. The folder walking code in DropShell uses FSSpecs
  2362. already, so I don't know what modifications you need to make.
  2363.  
  2364. [ start of included code deleted ]
  2365. >       error = PBGetCatInfoSync( &pb );
  2366. >       if( error == noErr )
  2367. >       {
  2368. >            // Right here I need something to convert the parameter block to
  2369. >            // an FSSpec for this item in the directory. So I can pass it
  2370. >            // my routine that either adds it to the FSSpec List (if it's a
  2371. >            // file) or calls this routine again (if it's a folder).
  2372. [ end of included code deleted ]
  2373. > Can I just copy the pb->h.fileParam.ioNamePtr, pb->c.hFileInfo.ioFlParID,
  2374. > and pb.hFileInfo.ioVRefNum fields of the parameter block to the the
  2375. > FSSpec? or do I need to do some other stuff? Do I need to any special
  2376. > handling of alias's?
  2377.  
  2378.  
  2379. Well, let's take your q's one at a time. 
  2380.  
  2381. 1) You _can_ just copy the relevant fields of the param block into an
  2382. FSSpec, and go from there. This is what the DropShell does, and it will
  2383. work. However, Apple has advised against building FSSpecs by hand, and
  2384. recomends calling FSMakeFSSpec instead. 
  2385.  
  2386. 2) If you want to resolve alias files while you are walking the file tree,
  2387. you can just call ResolveAliasFile () which will do all the alias
  2388. traversal for you. _However_, you need to ensure that your loop will
  2389. terminate. Imagine the following case:
  2390.  
  2391.    You have a folder "one"
  2392.       Inside it is a folder "two"
  2393.          inside it is a file "three"
  2394.          and a file "four", which is an alias to "one".
  2395.  
  2396. Have fun.
  2397. -- Marshall
  2398.  
  2399. -- 
  2400. Marshall Clow
  2401. Aladdin Systems
  2402. mclow@san_marcos.csusm.edu
  2403.  
  2404. ---------------------------
  2405.  
  2406. >From afrancke@netcom.com (Andrew Francke)
  2407. Subject: Q: Reentrancy and PowerMac Runtime Model
  2408. Date: Mon, 11 Jul 1994 03:13:46 GMT
  2409. Organization: Netcom Online Communications Services (408-241-9760 login: guest)
  2410.  
  2411. Even after scouring IM:PowerPC System Software, I yet labor under the
  2412. thick delusion that there is no way to prevent concurrency/reentrancy
  2413. on the PowerMac running native code. Whereas poking the SR worked just
  2414. fine before to keep interrupt code from unhappily butting in while
  2415. regular code was updating head and tail pointers on lists, there seems
  2416. to be no such mention of an equivalent "Critical Section" API on
  2417. PowerMac. Yea, verily, I believe it is not possible and am now
  2418. contemplating abandoning all Macintosh development. Say it ain't so.
  2419.  
  2420.  
  2421. P.S. While you're at it, tell me how it's possible to page-lock an
  2422. arbitrary range of memory while running native. Does the VM API
  2423. described in IM:Memory still apply? Or is it just, "tough luck --
  2424. you'll have to put everything you want in the system heap." Finally,
  2425. when (if ever) is the device driver interface going to be revved so
  2426. that drivers can be written native? IMHO, this is the dirtiest secret
  2427. kept by the Mac rags as device drivers far and away make the machine.
  2428.  
  2429. +++++++++++++++++++++++++++
  2430.  
  2431. >From rmah@panix.com (Robert Mah)
  2432. Date: Mon, 11 Jul 1994 01:04:22 -0500
  2433. Organization: One Step Beyond
  2434.  
  2435. afrancke@netcom.com (Andrew Francke) wrote:
  2436.  
  2437. ) Even after scouring IM:PowerPC System Software, I yet labor under the
  2438. ) thick delusion that there is no way to prevent concurrency/reentrancy
  2439. ) on the PowerMac running native code. Whereas poking the SR worked just
  2440. ) fine before to keep interrupt code from unhappily butting in while
  2441. ) regular code was updating head and tail pointers on lists, there seems
  2442. ) ...
  2443.  
  2444. What an extremely nasty way to check for interupts :-)
  2445.  
  2446. I simply use the OS queue routines.  Enqueue and Dequeue both disable
  2447. interupts so you can be SURE you're VBL's, callbacks and whatnot all
  2448. work nicely together.
  2449.  
  2450. Cheers,
  2451. Rob
  2452. _____________________________________________________________________
  2453. Robert S. Mah    :  Macintosh software development  :    212.947.6507
  2454. One Step Beyond  :      and network consulting      :  rmah@panix.com
  2455.  
  2456. +++++++++++++++++++++++++++
  2457.  
  2458. >From zstern@adobe.com (Zalman Stern)
  2459. Date: Mon, 11 Jul 1994 08:26:28 GMT
  2460. Organization: Adobe Systems Incorporated
  2461.  
  2462. Andrew Francke writes
  2463. > Even after scouring IM:PowerPC System Software, I yet labor under the
  2464. > thick delusion that there is no way to prevent concurrency/reentrancy
  2465. > on the PowerMac running native code. Whereas poking the SR worked just
  2466. > fine before to keep interrupt code from unhappily butting in while
  2467. > regular code was updating head and tail pointers on lists, there seems
  2468. > to be no such mention of an equivalent "Critical Section" API on
  2469. > PowerMac. Yea, verily, I believe it is not possible and am now
  2470. > contemplating abandoning all Macintosh development. Say it ain't so.
  2471.  
  2472. For updating queues in native code, the load-reserved/store-conditional  
  2473. mechanism is what you want to use. The mnemonics are lwarx and stwcx.  
  2474. respectively. There are examples on their usage in Appendix G of the MPC601  
  2475. User's Manual.
  2476.  
  2477. > P.S. While you're at it, tell me how it's possible to page-lock an
  2478. > arbitrary range of memory while running native. Does the VM API
  2479. > described in IM:Memory still apply?
  2480.  
  2481. It certainly should. (I.e. I haven't tried this, but I expect there's a  
  2482. moderate amount of 68k Mac software that would break if things did not work  
  2483. this way.)
  2484. --
  2485. Zalman Stern           zalman@adobe.com            (415) 962 3824
  2486. Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
  2487. `Wait a second! This is just an octahedron suspended in blue liquid.' - JT
  2488.  
  2489. +++++++++++++++++++++++++++
  2490.  
  2491. >From mxmora@unix.sri.com (Matthew Xavier Mora)
  2492. Date: Mon, 11 Jul 1994 14:32:15 -0700
  2493. Organization: SRI International
  2494.  
  2495. In article <afranckeCsrAAz.95I@netcom.com>, afrancke@netcom.com (Andrew
  2496. Francke) wrote:
  2497.  
  2498. > on the PowerMac running native code. Whereas poking the SR worked just
  2499. > fine before to keep interrupt code from unhappily butting in while
  2500. > regular code was updating head and tail pointers on lists, there seems
  2501. > to be no such mention of an equivalent "Critical Section" API on
  2502. > PowerMac.
  2503.  
  2504. This is one thing that they say will die a horrible death in Copland.
  2505.  
  2506. Do not set SR!
  2507.  
  2508.  
  2509.  
  2510. > you'll have to put everything you want in the system heap." Finally,
  2511. > when (if ever) is the device driver interface going to be revved so
  2512. > that drivers can be written native? IMHO, this is the dirtiest secret
  2513. > kept by the Mac rags as device drivers far and away make the machine.
  2514.  
  2515. You'll have to wait for Copland release for the new Native Driver
  2516. support. Write  them at their Applink address if you want more information.
  2517. I don't know the address offhand. Its microkernel.<something>.
  2518.  
  2519.  
  2520.  
  2521. Xavier
  2522.  
  2523. -- 
  2524. Matt Mora mxmora@unix.sri.com
  2525. Testing Neswatcher
  2526.  
  2527. +++++++++++++++++++++++++++
  2528.  
  2529. >From quinn@cs.uwa.edu.au (Quinn "The Eskimo!")
  2530. Date: Tue, 12 Jul 1994 10:45:59 +0800
  2531. Organization: Department of Computer Science, The University of Western Australia
  2532.  
  2533. In article <afranckeCsrAAz.95I@netcom.com>, afrancke@netcom.com (Andrew
  2534. Francke) wrote:
  2535.  
  2536. >Finally,
  2537. >when (if ever) is the device driver interface going to be revved so
  2538. >that drivers can be written native? IMHO, this is the dirtiest secret
  2539. >kept by the Mac rags as device drivers far and away make the machine.
  2540.  
  2541. You can write your drivers native, it's just that you have to have some
  2542. 68K glue at the front and thereby take a mixed-mode switch on every entry
  2543. to them.  But even if there was a native API you'd still be taking a
  2544. mixed-mode switch because the Device Manager (including the bit that
  2545. fields interrupts) is emulated.  So if you do a *lot* of work in your
  2546. device driver then writing it native would make sense.
  2547.  
  2548. All this mess is going to be sorted out in Copland.  Which means that a
  2549. lot of device drivers are going to have to be rewritten.
  2550. -- 
  2551. Quinn "The Eskimo!"      <quinn@cs.uwa.edu.au>     "Support HAVOC!"
  2552. Department of Computer Science, The University of Western Australia
  2553.   Who missed that session at WWDC and is desperately seeking the
  2554.   presentation CD.
  2555.  
  2556. +++++++++++++++++++++++++++
  2557.  
  2558. >From steele@isi.edu (Craig Steele)
  2559. Date: Tue, 12 Jul 1994 12:14:30 -0800
  2560. Organization: USC Information Sciences Institute
  2561.  
  2562. In article <mxmora-1107941432150001@xavier.sri.com>, mxmora@unix.sri.com 
  2563. (Matthew Xavier Mora) writes:
  2564. > You'll have to wait for Copland release for the new Native Driver 
  2565. > support. Write  them at their Applink address
  2566.  
  2567. Judging from the preliminary draft of "Designing PCI Cards and Drivers for 
  2568. Power Macintosh Computers" that arrived in my mailbox yesterday, bits of the 
  2569. future are coming a bit sooner.  A final PCI Card Developer's Kit for 
  2570. PowerMacs is said to be scheduled for APDA release in the "summer of 1994."  
  2571. The PCI runtime drivers use native interfaces.  You might be able to get a 
  2572. copy of the preliminary draft by contacting them at 
  2573. apple.pci.applelink.apple.com.
  2574.  
  2575.  
  2576. Craig S. Steele, steele@isi.edu - Not yet Institutionalized
  2577.  
  2578.  
  2579. +++++++++++++++++++++++++++
  2580.  
  2581. >From telesis@ecf.toronto.edu (Telesis North)
  2582. Date: Wed, 13 Jul 1994 04:19:47 GMT
  2583. Organization: telesis north & screen door company
  2584.  
  2585. In article <quinn-1207941045590001@edu-dynamic1.educ.ecel.uwa.edu.au>,
  2586. Quinn "The Eskimo!" <quinn@cs.uwa.edu.au> wrote:
  2587. >All this mess is going to be sorted out in Copland.  Which means that a
  2588. >lot of device drivers are going to have to be rewritten.
  2589.  
  2590. Actually, _all_ the device drivers are going to have to be re-written (or
  2591. break). That was my favourite quote out of the WWCC,
  2592.  
  2593.     "Under Copland, (current) 68K device drivers will not run."
  2594.  
  2595. Heh.
  2596.  
  2597. --
  2598. Roger Pantos                 Telesis North, Inc.           telesisnorth
  2599. Mac Software Guy             telesis@ecf.toronto.edu       (AppleLink)
  2600. Contrary to popular belief, green eggs & ham suck big time.
  2601.  
  2602. +++++++++++++++++++++++++++
  2603.  
  2604. >From quinn@cs.uwa.edu.au (Quinn "The Eskimo!")
  2605. Date: Thu, 14 Jul 1994 11:20:10 +0800
  2606. Organization: Department of Computer Science, The University of Western Australia
  2607.  
  2608. In article <Csv2oz.KKK@ecf.toronto.edu>, telesis@ecf.toronto.edu (Telesis
  2609. North) wrote:
  2610.  
  2611. >In article <quinn-1207941045590001@edu-dynamic1.educ.ecel.uwa.edu.au>,
  2612. >Quinn "The Eskimo!" <quinn@cs.uwa.edu.au> wrote:
  2613. >>All this mess is going to be sorted out in Copland.  Which means that a
  2614. >>lot of device drivers are going to have to be rewritten.
  2615. >
  2616. >Actually, _all_ the device drivers are going to have to be re-written (or
  2617. >break). That was my favourite quote out of the WWCC,
  2618. >
  2619. >        "Under Copland, (current) 68K device drivers will not run."
  2620.  
  2621. Well this is an interesting question.  I didn't catch that session at WWDC
  2622. but I can see no reason why software only device drivers (such .Notify and
  2623. .Reminder) couldn't be supported.  These are just using the Device Manager
  2624. as a kludgy share library system that gives you non-interrupt time.  So
  2625. was there any comment about non-hardware device drivers?
  2626.  
  2627. >Roger Pantos
  2628.  
  2629. Hi Roger!  Maybe if your real name was something other that Telesis North
  2630. I'd catch your postings more often (:
  2631. -- 
  2632. Quinn "The Eskimo!"      <quinn@cs.uwa.edu.au>     "Support HAVOC!"
  2633. Department of Computer Science, The University of Western Australia
  2634.  
  2635. +++++++++++++++++++++++++++
  2636.  
  2637. >From rang@winternet.com (Anton Rang)
  2638. Date: 14 Jul 1994 04:24:00 GMT
  2639. Organization: Trillium Research, Inc.
  2640.  
  2641. In article <afranckeCsrAAz.95I@netcom.com> afrancke@netcom.com (Andrew Francke) writes:
  2642. >Even after scouring IM:PowerPC System Software, I yet labor under the
  2643. >thick delusion that there is no way to prevent concurrency/reentrancy
  2644. >on the PowerMac running native code.
  2645.  
  2646.   You're right!  Well, more or less.  You can change the SR by going
  2647. back into 68K code, and since all interrupts are currently dispatched
  2648. through the emulator, this will block them from being processed until
  2649. you change the SR back.  But (a) this will break, and (b) this will be
  2650. incredibly slow.  Don't do it if you don't have to.
  2651.  
  2652. >Whereas poking the SR worked just
  2653. >fine before to keep interrupt code from unhappily butting in while
  2654. >regular code was updating head and tail pointers on lists
  2655.  
  2656.   Well, in this case you can either (a) call Enqueue/Dequeue, which is
  2657. slow because of the mode switch but will be atomic, or (b) use a
  2658. little assembly language to call the lwarx/stwcx instructions.  Check
  2659. your manual for details.
  2660.  
  2661. >there seems to be no such mention of an equivalent "Critical Section"
  2662. >API on PowerMac.
  2663.  
  2664.   There will be.  Unfortunately, it's not there yet.  The hardware is
  2665. ahead of the software, currently.
  2666.  
  2667. >P.S. While you're at it, tell me how it's possible to page-lock an
  2668. >arbitrary range of memory while running native. Does the VM API
  2669. >described in IM:Memory still apply?
  2670.  
  2671.   Yes, that API still works.  (All the current APIs work, actually.)
  2672.  
  2673. >Finally, when (if ever) is the device driver interface going to be
  2674. >revved so that drivers can be written native?
  2675.  
  2676.   With the release of PCI-based Macintoshes, at first, and then with
  2677. the next major system release (for older PowerMacs too presumably).  I
  2678. wish it were sooner, I *hate* debugging my current driver.  :)
  2679. --
  2680. Anton Rang (rang@winternet.com)
  2681.  
  2682. +++++++++++++++++++++++++++
  2683.  
  2684. >From telesis@ecf.toronto.edu (Telesis North)
  2685. Date: Thu, 14 Jul 1994 04:47:49 GMT
  2686. Organization: Roger @ Telesis North
  2687.  
  2688. In article <quinn-1407941120100001@edu-dynamic1.educ.ecel.uwa.edu.au>,
  2689. Quinn "The Eskimo!" <quinn@cs.uwa.edu.au> wrote:
  2690. >
  2691. >Well this is an interesting question.  I didn't catch that session at WWDC
  2692. >but I can see no reason why software only device drivers (such .Notify and
  2693. >.Reminder) couldn't be supported.  These are just using the Device Manager
  2694. >as a kludgy share library system that gives you non-interrupt time.  So
  2695. >was there any comment about non-hardware device drivers?
  2696.  
  2697. I don't remember any; I just remember the speaker (Russell?) being
  2698. pretty blunt about it. My understanding is that they're planning on
  2699. ripping out the entire toolbox-level I/O architecture, along with
  2700. the 68K-centric interrupt services, and heaving it off the dock with
  2701. a huge sigh of relief. (It will of course be replaced with a spiffy
  2702. new re-entrant driver model with a message-passing interface to the
  2703. microkernel that will make life wonderful for everyone, once they've
  2704. re-written their drivers.)
  2705.  
  2706. I agree with your point, though. I'd say an easy 50% of the drivers
  2707. running on my machine are just there to provide user interface hacks
  2708. (or other software-only goodies). Come to think of it, it's probably
  2709. mostly intercine warfare between the Now Utilities and everyone else...
  2710.  
  2711. The problem is that most of these are so skanky, I'm not sure how far
  2712. you'd have to go, emulation-wise, to get any level of backward
  2713. compatibility.
  2714.  
  2715. I suppose that one could write an early-load INIT that patched
  2716. OpenDriver(), GetDCtlEntry() and friends, and used a faceless
  2717. background app to provide non-interrupt time to the drivers in
  2718. the custom entry table, but you'd still have people looking
  2719. for familiar things in the global Unit Table in the Toolbox
  2720. space, not to mention making asynchronous PBControl calls with
  2721. oddball semantics... I shudder even to think about it. :-)
  2722.  
  2723. Copland is going to break a lot of software, in the name of
  2724. performance. Not necessarily straight-line application software,
  2725. but lots of stand-alone gadgets and integrated systems. (Anyone
  2726. holding out any hope for FaxSTF?) 
  2727.  
  2728. Should Apple devote engineer and QA time to emulating the old driver
  2729. model? Tough question. I know I'm not going to - I'm going to re-write
  2730. our drivers (and turn them into processes, most likely).
  2731.  
  2732. >Hi Roger!  Maybe if your real name was something other that Telesis North
  2733. >I'd catch your postings more often (:
  2734.  
  2735. Yeah, yeah. :-)  I still get my news fix through an ancient Unix shell
  2736. account that we pay a university through the nose for. I'm thinking that
  2737. the time I could spend reading through the man pages might be better
  2738. spent pestering people to get my Mac IP-connected. (Still, beats
  2739. chipping out TCP packets on stone tablets, which is what we did in the
  2740. old days...)
  2741.  
  2742. --
  2743. Roger Pantos                 Telesis North, Inc.           telesisnorth
  2744. Mac Software Guy             telesis@ecf.toronto.edu       (AppleLink)
  2745. I can think of nothing more odious than a philosophy that forces its
  2746. beliefs or its conscriptions on those who are unwilling or uninterested
  2747. in having them.
  2748.  
  2749. +++++++++++++++++++++++++++
  2750.  
  2751. >From chewey@nesw.mv.com (Matthew E. Axsom)
  2752. Date: Fri, 15 Jul 1994 13:30:42 GMT
  2753. Organization: New England Software Works
  2754.  
  2755. In article <quinn-1407941120100001@edu-dynamic1.educ.ecel.uwa.edu.au>,
  2756. quinn@cs.uwa.edu.au (Quinn "The Eskimo!") wrote:
  2757.  
  2758. > In article <Csv2oz.KKK@ecf.toronto.edu>, telesis@ecf.toronto.edu (Telesis
  2759. > North) wrote:
  2760. > >In article <quinn-1207941045590001@edu-dynamic1.educ.ecel.uwa.edu.au>,
  2761. > >Quinn "The Eskimo!" <quinn@cs.uwa.edu.au> wrote:
  2762. > >>All this mess is going to be sorted out in Copland.  Which means that a
  2763. > >>lot of device drivers are going to have to be rewritten.
  2764. > >
  2765. > >Actually, _all_ the device drivers are going to have to be re-written (or
  2766. > >break). That was my favourite quote out of the WWCC,
  2767. > >
  2768. > >        "Under Copland, (current) 68K device drivers will not run."
  2769. > Well this is an interesting question.  I didn't catch that session at WWDC
  2770. > but I can see no reason why software only device drivers (such .Notify and
  2771. > .Reminder) couldn't be supported.  These are just using the Device Manager
  2772. > as a kludgy share library system that gives you non-interrupt time.  So
  2773. > was there any comment about non-hardware device drivers?
  2774. I believe that they used that as a blanket statement at first and later
  2775. backed away from that and said that the current driver model would still
  2776. run as long as it was a "softwre driver" (e.g. .Reminder or .Notify) and
  2777. not a "hardware driver".  I believe they said that as long as it doesn't
  2778. touch the hardware directly, the old drivers could still be used.
  2779.  
  2780. -Chewey
  2781. struct Matthew: E, Axsom { //chewey@nesw.mv.com
  2782.   Matthew(void) : E(), Axsom() {}
  2783.   Boolean macSoftwareEngineer(long future) {return future==Random();}
  2784.   Boolean newEnglandSoftwareWorks(StringPtr name) {return true;}
  2785. };
  2786.  
  2787. +++++++++++++++++++++++++++
  2788.  
  2789. >From absurd@apple.com (Tim Dierks)
  2790. Date: Fri, 22 Jul 1994 23:27:05 GMT
  2791. Organization: Apple Computer, Inc.
  2792.  
  2793. In article <Cswynq.Bx1@ecf.toronto.edu>, telesis@ecf.toronto.edu (Telesis
  2794. North) wrote:
  2795. > In article <quinn-1407941120100001@edu-dynamic1.educ.ecel.uwa.edu.au>,
  2796. > Quinn "The Eskimo!" <quinn@cs.uwa.edu.au> wrote:
  2797. > >
  2798. > >Well this is an interesting question.  I didn't catch that session at WWDC
  2799. > >but I can see no reason why software only device drivers (such .Notify and
  2800. > >.Reminder) couldn't be supported.  These are just using the Device Manager
  2801. > >as a kludgy share library system that gives you non-interrupt time.  So
  2802. > >was there any comment about non-hardware device drivers?
  2803. > I don't remember any; I just remember the speaker (Russell?) being
  2804. > pretty blunt about it. My understanding is that they're planning on
  2805. > ripping out the entire toolbox-level I/O architecture, along with
  2806. > the 68K-centric interrupt services, and heaving it off the dock with
  2807. > a huge sigh of relief. (It will of course be replaced with a spiffy
  2808. > new re-entrant driver model with a message-passing interface to the
  2809. > microkernel that will make life wonderful for everyone, once they've
  2810. > re-written their drivers.)
  2811. > I agree with your point, though. I'd say an easy 50% of the drivers
  2812. > running on my machine are just there to provide user interface hacks
  2813. > (or other software-only goodies). Come to think of it, it's probably
  2814. > mostly intercine warfare between the Now Utilities and everyone else...
  2815. > The problem is that most of these are so skanky, I'm not sure how far
  2816. > you'd have to go, emulation-wise, to get any level of backward
  2817. > compatibility.
  2818.  
  2819. Copland will support the Device manager driver model for dispatching to
  2820. old-style drivers; this level of compatibility should allow many drivers
  2821. to continue to work, especially those which are software-only, and just
  2822. manipulate data or dispatch to other drivers or toolboxes. Of course, this
  2823. doesn't guarantee the software inside the driver will still work
  2824. (depending on its assumptions), but we'll try to support the mechanism as
  2825. best we can. 68K drivers which touch hardware or which get invoked to
  2826. handle hardware interrupts will most likely not be compatible.
  2827.  
  2828. > Copland is going to break a lot of software, in the name of
  2829. > performance. Not necessarily straight-line application software,
  2830. > but lots of stand-alone gadgets and integrated systems. (Anyone
  2831. > holding out any hope for FaxSTF?) 
  2832. > Should Apple devote engineer and QA time to emulating the old driver
  2833. > model? Tough question. I know I'm not going to - I'm going to re-write
  2834. > our drivers (and turn them into processes, most likely).
  2835.  
  2836. Copland won't be 100% compatible, but a lot of the stuff we break we'll
  2837. break because it's fundamentally incompatible with progress; stuff that's
  2838. bad, but not that bad, we'll just have to see...
  2839.  
  2840. > Roger Pantos                 Telesis North, Inc.           telesisnorth
  2841.  
  2842. -- 
  2843. Tim Dierks
  2844. absurd@apple.com
  2845.  
  2846. ---------------------------
  2847.  
  2848. >From stk@uropax.contrib.de (Stefan Kurth)
  2849. Subject: Std filter proc trashes register D3!
  2850. Date: 18 Jul 1994 14:40:50 +0200
  2851. Organization: Contributed Software GbR
  2852.  
  2853. Just discovered another system software bug: the standard filter proc
  2854. (the one that you get with GetStdFilterProc() ) distroys the contents
  2855. of the D3 register. Took me quite some time to figure out why one my
  2856. variables kept changing all by itself...
  2857.  
  2858. Is this a known bug? If not, how do I go about reporting it to Apple?
  2859.  
  2860. ________________________________________________________________________
  2861. Stefan Kurth                 Berlin, Germany              stk@contrib.de
  2862.  
  2863. +++++++++++++++++++++++++++
  2864.  
  2865. >From D.A.G.Gillies@bradford.ac.uk (David Gillies)
  2866. Date: Mon, 18 Jul 1994 15:13:25 GMT
  2867. Organization: Unseen University, Ankh-Morpork
  2868.  
  2869. In article <30dt8i$32d@uropax.contrib.de> stk@uropax.contrib.de (Stefan Kurth) writes:
  2870. >Just discovered another system software bug: the standard filter proc
  2871. >(the one that you get with GetStdFilterProc() ) distroys the contents
  2872. >of the D3 register. Took me quite some time to figure out why one my
  2873. >variables kept changing all by itself...
  2874. >Is this a known bug? If not, how do I go about reporting it to Apple?
  2875. >
  2876. This definitely sounds like a bug. If nothing else, the compiler should make
  2877. callbacks safe by padding where necessary with MOVEM. It's only D0-D2 and
  2878. A0/A1 that routines are meant to be allowed to stamp on, and compilers
  2879. should recognize this and guard against it. I might be wrong, but this does
  2880. seem suspicious.
  2881.  
  2882. Personally I hate the standard filter proc, but I always prefer to roll my own.
  2883.  
  2884. ______________________________________________________________________
  2885. David A. G. Gillies                     (D.A.G.Gillies@bradford.ac.uk)
  2886.       University of Bradford, Bradford, West Yorkshire, England
  2887. (c) 1994 Wittgenstein and The Furniture Depository of The Living Dead
  2888.  
  2889. A little learning is a dangerous thing - but not half as dangerous as a
  2890. lot of ignorance.
  2891. - ---------------------REPLIES VIA EMAIL PLEASE-----------------------
  2892. _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
  2893.  
  2894. +++++++++++++++++++++++++++
  2895.  
  2896. >From stk@uropax.contrib.de (Stefan Kurth)
  2897. Date: 19 Jul 1994 01:16:49 +0200
  2898. Organization: Contributed Software GbR
  2899.  
  2900. In article <1994Jul18.151325.8525@bradford.ac.uk>,
  2901. David Gillies <D.A.G.Gillies@bradford.ac.uk> wrote:
  2902.  
  2903. > In article <30dt8i$32d@uropax.contrib.de> stk@uropax.contrib.de
  2904. > (Stefan Kurth) writes:
  2905. >
  2906. > > Is this a known bug? If not, how do I go about reporting it to Apple?
  2907. >
  2908. > This definitely sounds like a bug.
  2909.  
  2910. Sure it is - my question was if it is a _known_ bug...  :-)
  2911.  
  2912. > If nothing else, the compiler should make callbacks safe by padding where
  2913. > necessary with MOVEM. It's only D0-D2 and A0/A1 that routines are meant
  2914. > to be allowed to stamp on, and compilers should recognize this and guard
  2915. > against it.
  2916.  
  2917. In this case it's not the compiler's job to save registers (I mean, not _my_
  2918. compiler's; it would have been the job of whatever compiler Apple used to
  2919. compile their system software). The standard filter proc should save the
  2920. registers that it uses; however, it saves only D4-D7, but also uses D3.
  2921.  
  2922. > Personally I hate the standard filter proc, but I always prefer to roll
  2923. > my own.
  2924.  
  2925. Would you explain why? I have found it extremely handy. It does a lot of
  2926. work for you.
  2927.  
  2928. ________________________________________________________________________
  2929. Stefan Kurth                 Berlin, Germany              stk@contrib.de
  2930.  
  2931. +++++++++++++++++++++++++++
  2932.  
  2933. >From Alexander M. Rosenberg <alexr@apple.com>
  2934. Date: Tue, 19 Jul 1994 02:20:19 GMT
  2935. Organization: Hackers Anonymous
  2936.  
  2937. In article <30dt8i$32d@uropax.contrib.de> Stefan Kurth, stk@uropax.contrib.de
  2938. writes:
  2939. > Just discovered another system software bug: the standard filter proc
  2940. > (the one that you get with GetStdFilterProc() ) distroys the contents
  2941. > of the D3 register. Took me quite some time to figure out why one my
  2942. > variables kept changing all by itself...
  2943. >  
  2944. > Is this a known bug? If not, how do I go about reporting it to Apple?
  2945.  
  2946. Yes. Thank you for taking the time to track it down. I believe that it is
  2947. under consideration for our next System Update release.
  2948. - -------------------------------------------------------------------------
  2949. -  Alexander M. Rosenberg  - INTERNET: alexr@apple.com      - Yoyodyne    -
  2950. -  330 Waverley St., Apt B - UUCP:ucbvax!apple!alexr        - Propulsion  -
  2951. -  Palo Alto, CA 94301     -                                - Systems     -
  2952. -  (415) 329-8463          - Nobody is my employer so       - :-)         -
  2953. -                          - nobody cares what I say.       -             -
  2954.  
  2955. +++++++++++++++++++++++++++
  2956.  
  2957. >From David A Lyons <dlyons@apple.com>
  2958. Date: Tue, 19 Jul 1994 06:00:07 GMT
  2959. Organization: Apple Computer, Inc.
  2960.  
  2961. In article <30dt8i$32d@uropax.contrib.de> Stefan Kurth,
  2962. stk@uropax.contrib.de writes:
  2963. > Just discovered another system software bug: the standard filter proc
  2964. > (the one that you get with GetStdFilterProc() ) distroys the contents
  2965. > of the D3 register. Took me quite some time to figure out why one my
  2966. > variables kept changing all by itself...
  2967. >  
  2968. > Is this a known bug? If not, how do I go about reporting it to Apple?
  2969.  
  2970. It's a known bug in ROMs earlier than the Quadra 840av/660av; for now
  2971. you'll have to work around it in your application.
  2972.  
  2973. Dave Lyons
  2974. Mr Tangent
  2975.  
  2976. +++++++++++++++++++++++++++
  2977.  
  2978. >From jonasw@lysator.liu.se (Jonas Wallden)
  2979. Date: 19 Jul 1994 16:59:31 GMT
  2980. Organization: (none)
  2981.  
  2982. David A Lyons <dlyons@apple.com> writes:
  2983. >In article <30dt8i$32d@uropax.contrib.de> Stefan Kurth,
  2984. >stk@uropax.contrib.de writes:
  2985. >> Just discovered another system software bug: the standard filter proc
  2986. >> (the one that you get with GetStdFilterProc() ) distroys the contents
  2987. >> of the D3 register. Took me quite some time to figure out why one my
  2988. >> variables kept changing all by itself...
  2989. >>  
  2990. >> Is this a known bug? If not, how do I go about reporting it to Apple?
  2991. >
  2992. >It's a known bug in ROMs earlier than the Quadra 840av/660av; for now
  2993. >you'll have to work around it in your application.
  2994. >
  2995. >Dave Lyons
  2996. >Mr Tangent
  2997.  
  2998. On a related subject: I installed a memory grow proc in an application that
  2999. uses a small heap, and that also uses StandardFile to select folders. I
  3000. noticed that my grow proc was called while the SF dialog was being shown,
  3001. and that SF tried to allocate a large memory block (size > 64 Kb). Of course
  3002. it failed to find the free memory but everything works ok anyway.
  3003.  
  3004. Is this just some cache memory that it tries to allocate for the fancy
  3005. color icons used by Hardware System Update 3.0? I will have to check again
  3006. to make sure it's not one of my system extensions playing a trick on me.
  3007.  
  3008. -- Jonas Wallden
  3009. --
  3010. -- Jonas Wallden -- Internet: jonasw@lysator.liu.se -- AppleLink: sw1369 --
  3011.  
  3012. +++++++++++++++++++++++++++
  3013.  
  3014. >From dean@genmagic.com (Dean Yu)
  3015. Date: 19 Jul 1994 18:35:23 GMT
  3016. Organization: General Magic, Inc.
  3017.  
  3018. In article <30dt8i$32d@uropax.contrib.de>, stk@uropax.contrib.de (Stefan
  3019. Kurth) wrote:
  3020. > Just discovered another system software bug: the standard filter proc
  3021. > (the one that you get with GetStdFilterProc() ) distroys the contents
  3022. > of the D3 register. Took me quite some time to figure out why one my
  3023. > variables kept changing all by itself...
  3024. >  
  3025. > Is this a known bug? If not, how do I go about reporting it to Apple?
  3026.  
  3027.   This is a known bug. (Well, I knew about it when I was there...) I seem
  3028. to remember writing some inline code to work around this problem, but I
  3029. don't remember what that was for.
  3030.  
  3031. -- Dean Yu
  3032.    Negative Ethnic Role Model
  3033.    General Magic, Inc.
  3034.  
  3035. ---------------------------
  3036.  
  3037. >From Jim Conner <jc30@cornell.edu>
  3038. Subject: Which NIM for serial port info?
  3039. Date: 25 Jul 1994 02:13:58 GMT
  3040. Organization: Cornell University
  3041.  
  3042. Hello,
  3043.  
  3044. I have been developing a somewhat specialized application for analysis of
  3045. data generated by an instrument in our lab.  Currently, the data is taken
  3046. from the instrument's small display unit and entered by hand into the
  3047. application.  The data is also available from the instrument's RS-232
  3048. port.  The hope is that this data can be sent directly from the
  3049. instrument to the Mac by way of one of the Mac's serial ports.
  3050.  
  3051. I think that I have a grip on the hardware aspect of this connection
  3052. (wiring one of the Mac's RS-422 serial ports so it looks like RS-232, and
  3053. making the correct cable to the instrument).  I would like to know,
  3054. though, (1) which New Inside Macintosh book covers serial port
  3055. manipulations, and (2) if anyone has any other references that have been
  3056. helpful with this sort of problem.
  3057.  
  3058. Thanks,
  3059. Jim Conner
  3060.  
  3061. +++++++++++++++++++++++++++
  3062.  
  3063. >From bierman@caelab1.cae.wisc.edu (Peter Bierman)
  3064. Date: Sun, 24 Jul 1994 23:43:13 -0500
  3065. Organization: The Metropolis BBS <614/846-1911> Info-Mac on CD!
  3066.  
  3067. In article <30v756$ghq@newsstand.cit.cornell.edu>, Jim Conner
  3068. <jc30@cornell.edu> wrote:
  3069.  
  3070.  
  3071. > I would like to know,
  3072. > though, (1) which New Inside Macintosh book covers serial port
  3073. > manipulations, and (2) if anyone has any other references that have been
  3074. > helpful with this sort of problem.
  3075.  
  3076. NIM: Devices. (I don't even know if it's out yet) Chapter 5.
  3077.  
  3078. Many people suggest "Terminal 2.2" as a great source for example code, in C.
  3079.  
  3080. -Peter
  3081.  
  3082. -- 
  3083. Peter Bierman                |"Sometimes I think that the surest sign
  3084. bierman@caelab1.cae.wisc.edu | that intelligent life exists elsewhere
  3085. The Metropolis 614/846-1911  | in the universe is that none of it has
  3086. 600+MB, 2CDs, 2Lines@14.4    | tried to contact us." --Calvin
  3087.  
  3088. ---------------------------
  3089.  
  3090. End of C.S.M.P. Digest
  3091. **********************
  3092.  
  3093.  
  3094.  
  3095.